From f7c0ef1f733a252a055e3b4be3bb7de31dd091a5 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 9 Aug 2023 12:47:58 +0200 Subject: [PATCH] Nodes: define rna of nodes in node file instead of rna_nodetree.cc The goal is to be able to define a node in as few files as possible. Currently, RNA definitions for nodes are put in `rna_nodetree.cc`. However, it seems surprisingly simple to move them from there to the node files. Of course this means that `makesrna.cc` won't generate these properties and their accessor functions anymore. Fortunately, C++ lambdas and the preprocessor make it fairly straight forward to generate those without the `makesrna` preprocessor. Using the preprocessor here is not great of course, but I'd argue that it feels less magical than it was before, so it's an improvement. This patch changes a few files to test the feasibility of this approach. Eventually, this approach should be used by all nodes. It can't be used for shader nodes for now, because cycles still relies on the C++ API generated by RNA. Right now, only properties are defined the node files. The `StructRNA` is still generated by `makesrna`. It seems feasible to generate it at runtime as well though with potentially minor RNA API changes. This is related to #75724. Pull Request: https://projects.blender.org/blender/blender/pulls/110840 --- source/blender/makesrna/RNA_define.h | 1 + source/blender/makesrna/intern/rna_define.cc | 5 ++ .../blender/makesrna/intern/rna_nodetree.cc | 70 +------------------ source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_rna_define.hh | 44 ++++++++++++ source/blender/nodes/NOD_static_types.h | 6 +- .../geometry/nodes/node_geo_curve_resample.cc | 37 ++++++++++ .../nodes/node_geo_set_curve_normal.cc | 18 +++++ .../nodes/node_geo_subdivision_surface.cc | 27 +++++++ 9 files changed, 139 insertions(+), 70 deletions(-) create mode 100644 source/blender/nodes/NOD_rna_define.hh diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h index e9cdcc8b1df..4a48873dc6f 100644 --- a/source/blender/makesrna/RNA_define.h +++ b/source/blender/makesrna/RNA_define.h @@ -454,6 +454,7 @@ void RNA_def_property_override_funcs(PropertyRNA *prop, const char *apply); void RNA_def_property_update_runtime(PropertyRNA *prop, const void *func); +void RNA_def_property_update_notifier(PropertyRNA *prop, int noteflag); void RNA_def_property_poll_runtime(PropertyRNA *prop, const void *func); void RNA_def_property_dynamic_array_funcs(PropertyRNA *prop, const char *getlength); diff --git a/source/blender/makesrna/intern/rna_define.cc b/source/blender/makesrna/intern/rna_define.cc index a035f8ac444..873909e2b9c 100644 --- a/source/blender/makesrna/intern/rna_define.cc +++ b/source/blender/makesrna/intern/rna_define.cc @@ -2925,6 +2925,11 @@ void RNA_def_property_update_runtime(PropertyRNA *prop, const void *func) prop->update = (UpdateFunc)func; } +void RNA_def_property_update_notifier(PropertyRNA *prop, const int noteflag) +{ + prop->noteflag = noteflag; +} + void RNA_def_property_poll_runtime(PropertyRNA *prop, const void *func) { if (prop->type == PROP_POINTER) { diff --git a/source/blender/makesrna/intern/rna_nodetree.cc b/source/blender/makesrna/intern/rna_nodetree.cc index e86eff98211..03077070c73 100644 --- a/source/blender/makesrna/intern/rna_nodetree.cc +++ b/source/blender/makesrna/intern/rna_nodetree.cc @@ -620,7 +620,7 @@ extern FunctionRNA rna_Node_draw_buttons_ext_func; extern FunctionRNA rna_Node_draw_label_func; } -static void rna_Node_socket_update(Main *bmain, Scene * /*scene*/, PointerRNA *ptr); +void rna_Node_socket_update(Main *bmain, Scene * /*scene*/, PointerRNA *ptr); int rna_node_tree_idname_to_enum(const char *idname) { @@ -2371,7 +2371,7 @@ static bool rna_Node_parent_poll(PointerRNA *ptr, PointerRNA value) return true; } -static void rna_Node_update(Main *bmain, Scene * /*scene*/, PointerRNA *ptr) +void rna_Node_update(Main *bmain, Scene * /*scene*/, PointerRNA *ptr) { bNodeTree *ntree = reinterpret_cast(ptr->owner_id); bNode *node = static_cast(ptr->data); @@ -4011,7 +4011,7 @@ static void rna_ShaderNode_socket_update(Main *bmain, Scene *scene, PointerRNA * rna_Node_update(bmain, scene, ptr); } -static void rna_Node_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr) +void rna_Node_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr) { rna_Node_update(bmain, scene, ptr); } @@ -9264,26 +9264,6 @@ static void def_geo_triangulate(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } -static void def_geo_subdivision_surface(StructRNA *srna) -{ - PropertyRNA *prop; - - RNA_def_struct_sdna_from(srna, "NodeGeometrySubdivisionSurface", "storage"); - prop = RNA_def_property(srna, "uv_smooth", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, nullptr, "uv_smooth"); - RNA_def_property_enum_items(prop, rna_enum_subdivision_uv_smooth_items); - RNA_def_property_enum_default(prop, SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES); - RNA_def_property_ui_text(prop, "UV Smooth", "Controls how smoothing is applied to UVs"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - - prop = RNA_def_property(srna, "boundary_smooth", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, nullptr, "boundary_smooth"); - RNA_def_property_enum_items(prop, rna_enum_subdivision_boundary_smooth_items); - RNA_def_property_enum_default(prop, SUBSURF_BOUNDARY_SMOOTH_ALL); - RNA_def_property_ui_text(prop, "Boundary Smooth", "Controls how open boundaries are smoothed"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); -} - static void def_geo_accumulate_field(StructRNA *srna) { PropertyRNA *prop; @@ -9483,17 +9463,6 @@ static void def_geo_curve_set_handle_positions(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } -static void def_geo_set_curve_normal(StructRNA *srna) -{ - PropertyRNA *prop; - - prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, nullptr, "custom1"); - RNA_def_property_enum_items(prop, rna_enum_curve_normal_modes); - RNA_def_property_ui_text(prop, "Mode", "Mode for curve normal evaluation"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); -} - static void def_geo_simulation_input(StructRNA *srna) { PropertyRNA *prop; @@ -10399,39 +10368,6 @@ static void def_geo_curve_primitive_quadrilateral(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } -static void def_geo_curve_resample(StructRNA *srna) -{ - PropertyRNA *prop; - - static EnumPropertyItem mode_items[] = { - {GEO_NODE_CURVE_RESAMPLE_EVALUATED, - "EVALUATED", - 0, - "Evaluated", - "Output the input spline's evaluated points, based on the resolution attribute for NURBS " - "and Bezier splines. Poly splines are unchanged"}, - {GEO_NODE_CURVE_RESAMPLE_COUNT, - "COUNT", - 0, - "Count", - "Sample the specified number of points along each spline"}, - {GEO_NODE_CURVE_RESAMPLE_LENGTH, - "LENGTH", - 0, - "Length", - "Calculate the number of samples by splitting each spline into segments with the specified " - "length"}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - RNA_def_struct_sdna_from(srna, "NodeGeometryCurveResample", "storage"); - - prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, mode_items); - RNA_def_property_ui_text(prop, "Mode", "How to specify the amount of samples"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); -} - static void def_geo_curve_fillet(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index d144ed032e0..a4d938636cd 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -67,6 +67,7 @@ set(SRC NOD_multi_function.hh NOD_node_declaration.hh NOD_register.hh + NOD_rna_define.hh NOD_shader.h NOD_socket.hh NOD_socket_declarations.hh diff --git a/source/blender/nodes/NOD_rna_define.hh b/source/blender/nodes/NOD_rna_define.hh new file mode 100644 index 00000000000..33ec1df6378 --- /dev/null +++ b/source/blender/nodes/NOD_rna_define.hh @@ -0,0 +1,44 @@ +/* SPDX-FileCopyrightText: 2023 Blender Foundation + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#include "RNA_define.h" + +/** + * Generates accessor methods for a property stored in `bNode->storage`. This is expected to be + * used in a node file that uses #NODE_STORAGE_FUNCS. + */ +#define RNA_def_property_enum_node_storage(prop, member) \ + RNA_def_property_enum_funcs_runtime( \ + prop, \ + [](PointerRNA *ptr, PropertyRNA * /*prop*/) -> int { \ + const bNode &node = *static_cast(ptr->data); \ + return node_storage(node).member; \ + }, \ + [](PointerRNA *ptr, PropertyRNA * /*prop*/, const int value) { \ + bNode &node = *static_cast(ptr->data); \ + node_storage(node).member = value; \ + }, \ + nullptr) + +/** + * Generates accessor methods for a property stored directly in the `bNode`, typically + * `bNode->custom1` or similar. + */ +#define RNA_def_property_enum_node(prop, member) \ + RNA_def_property_enum_funcs_runtime( \ + prop, \ + [](PointerRNA *ptr, PropertyRNA * /*prop*/) -> int { \ + const bNode &node = *static_cast(ptr->data); \ + return node.member; \ + }, \ + [](PointerRNA *ptr, PropertyRNA * /*prop*/, const int value) { \ + bNode &node = *static_cast(ptr->data); \ + node.member = value; \ + }, \ + nullptr) + +void rna_Node_update(Main *bmain, Scene *scene, PointerRNA *ptr); +void rna_Node_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 6d58d2a8a7b..222ebdd57bc 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -404,7 +404,7 @@ DefNode(GeometryNode, GEO_NODE_REMOVE_ATTRIBUTE, 0, "REMOVE_ATTRIBUTE", RemoveAt DefNode(GeometryNode, GEO_NODE_REPEAT_INPUT, def_geo_repeat_input, "REPEAT_INPUT", RepeatInput, "Repeat Input", "") DefNode(GeometryNode, GEO_NODE_REPEAT_OUTPUT, def_geo_repeat_output, "REPEAT_OUTPUT", RepeatOutput, "Repeat Output", "") DefNode(GeometryNode, GEO_NODE_REPLACE_MATERIAL, 0, "REPLACE_MATERIAL", ReplaceMaterial, "Replace Material", "Swap one material with another") -DefNode(GeometryNode, GEO_NODE_RESAMPLE_CURVE, def_geo_curve_resample, "RESAMPLE_CURVE", ResampleCurve, "Resample Curve", "Generate a poly spline for each input spline") +DefNode(GeometryNode, GEO_NODE_RESAMPLE_CURVE, 0, "RESAMPLE_CURVE", ResampleCurve, "Resample Curve", "Generate a poly spline for each input spline") DefNode(GeometryNode, GEO_NODE_REVERSE_CURVE, 0, "REVERSE_CURVE", ReverseCurve, "Reverse Curve", "Change the direction of curves by swapping their start and end data") DefNode(GeometryNode, GEO_NODE_ROTATE_INSTANCES, 0, "ROTATE_INSTANCES", RotateInstances, "Rotate Instances", "Rotate geometry instances in local or global space") DefNode(GeometryNode, GEO_NODE_SAMPLE_CURVE, def_geo_curve_sample, "SAMPLE_CURVE", SampleCurve, "Sample Curve", "Retrieve data from a point on a curve at a certain distance from its start") @@ -420,7 +420,7 @@ DefNode(GeometryNode, GEO_NODE_SELF_OBJECT, 0, "SELF_OBJECT", SelfObject, "Self DefNode(GeometryNode, GEO_NODE_SEPARATE_COMPONENTS, 0, "SEPARATE_COMPONENTS",SeparateComponents, "Separate Components", "Split a geometry into a separate output for each type of data in the geometry") DefNode(GeometryNode, GEO_NODE_SEPARATE_GEOMETRY, def_geo_separate_geometry, "SEPARATE_GEOMETRY", SeparateGeometry, "Separate Geometry", "Split a geometry into two geometry outputs based on a selection") DefNode(GeometryNode, GEO_NODE_SET_CURVE_HANDLES, def_geo_curve_set_handle_positions, "SET_CURVE_HANDLES", SetCurveHandlePositions, "Set Handle Positions", "Set the positions for the handles of Bézier curves") -DefNode(GeometryNode, GEO_NODE_SET_CURVE_NORMAL, def_geo_set_curve_normal, "SET_CURVE_NORMAL", SetCurveNormal, "Set Curve Normal", "Set the evaluation mode for curve normals") +DefNode(GeometryNode, GEO_NODE_SET_CURVE_NORMAL, 0, "SET_CURVE_NORMAL", SetCurveNormal, "Set Curve Normal", "Set the evaluation mode for curve normals") DefNode(GeometryNode, GEO_NODE_SET_CURVE_RADIUS, 0, "SET_CURVE_RADIUS", SetCurveRadius, "Set Curve Radius", "Set the radius of the curve at each control point") DefNode(GeometryNode, GEO_NODE_SET_CURVE_TILT, 0, "SET_CURVE_TILT", SetCurveTilt, "Set Curve Tilt", "Set the tilt angle at each curve control point") DefNode(GeometryNode, GEO_NODE_SET_ID, 0, "SET_ID", SetID, "Set ID", "Set the id attribute on the input geometry, mainly used internally for randomizing") @@ -439,7 +439,7 @@ DefNode(GeometryNode, GEO_NODE_STRING_JOIN, 0, "STRING_JOIN", StringJoin, "Join DefNode(GeometryNode, GEO_NODE_STRING_TO_CURVES, def_geo_string_to_curves, "STRING_TO_CURVES", StringToCurves, "String to Curves", "Generate a paragraph of text with a specific font, using a curve instance to store each character") DefNode(GeometryNode, GEO_NODE_SUBDIVIDE_CURVE, 0, "SUBDIVIDE_CURVE", SubdivideCurve, "Subdivide Curve", "Dividing each curve segment into a specified number of pieces") DefNode(GeometryNode, GEO_NODE_SUBDIVIDE_MESH, 0, "SUBDIVIDE_MESH", SubdivideMesh, "Subdivide Mesh", "Divide mesh faces into smaller ones without changing the shape or volume, using linear interpolation to place the new vertices") -DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, def_geo_subdivision_surface, "SUBDIVISION_SURFACE",SubdivisionSurface, "Subdivision Surface", "Divide mesh faces to form a smooth surface, using the Catmull-Clark subdivision method") +DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, 0, "SUBDIVISION_SURFACE",SubdivisionSurface, "Subdivision Surface", "Divide mesh faces to form a smooth surface, using the Catmull-Clark subdivision method") DefNode(GeometryNode, GEO_NODE_SWITCH, def_geo_switch, "SWITCH", Switch, "Switch", "Switch between two inputs") DefNode(GeometryNode, GEO_NODE_TRANSFORM_GEOMETRY, 0, "TRANSFORM_GEOMETRY", Transform, "Transform Geometry", "Translate, rotate or scale the geometry") DefNode(GeometryNode, GEO_NODE_TRANSLATE_INSTANCES, 0, "TRANSLATE_INSTANCES",TranslateInstances, "Translate Instances", "Move top-level geometry instances in local or global space") 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 23d4271db1e..d51336f7432 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc @@ -9,6 +9,8 @@ #include "UI_interface.hh" #include "UI_resources.hh" +#include "NOD_rna_define.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_curve_resample_cc { @@ -106,6 +108,39 @@ static void node_geo_exec(GeoNodeExecParams params) params.set_output("Curve", std::move(geometry_set)); } +static void node_rna(StructRNA *srna) +{ + PropertyRNA *prop; + + static EnumPropertyItem mode_items[] = { + {GEO_NODE_CURVE_RESAMPLE_EVALUATED, + "EVALUATED", + 0, + "Evaluated", + "Output the input spline's evaluated points, based on the resolution attribute for NURBS " + "and Bezier splines. Poly splines are unchanged"}, + {GEO_NODE_CURVE_RESAMPLE_COUNT, + "COUNT", + 0, + "Count", + "Sample the specified number of points along each spline"}, + {GEO_NODE_CURVE_RESAMPLE_LENGTH, + "LENGTH", + 0, + "Length", + "Calculate the number of samples by splitting each spline into segments with the specified " + "length"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_node_storage(prop, mode); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_ui_text(prop, "Mode", "How to specify the amount of samples"); + RNA_def_property_update_runtime(prop, (void *)rna_Node_socket_update); + RNA_def_property_update_notifier(prop, NC_NODE | NA_EDITED); +} + } // namespace blender::nodes::node_geo_curve_resample_cc void register_node_type_geo_curve_resample() @@ -123,4 +158,6 @@ void register_node_type_geo_curve_resample() ntype.updatefunc = file_ns::node_update; ntype.geometry_node_execute = file_ns::node_geo_exec; nodeRegisterType(&ntype); + + file_ns::node_rna(ntype.rna_ext.srna); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_normal.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_normal.cc index b6f25ff19ae..1dab06ddf16 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_normal.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_normal.cc @@ -7,6 +7,10 @@ #include "UI_interface.hh" #include "UI_resources.hh" +#include "NOD_rna_define.hh" + +#include "RNA_enum_types.h" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_set_curve_normal_cc { @@ -58,6 +62,18 @@ static void node_geo_exec(GeoNodeExecParams params) params.set_output("Curve", std::move(geometry_set)); } +static void node_rna(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_node(prop, custom1); + RNA_def_property_enum_items(prop, rna_enum_curve_normal_modes); + RNA_def_property_ui_text(prop, "Mode", "Mode for curve normal evaluation"); + RNA_def_property_update_runtime(prop, (void *)rna_Node_update); + RNA_def_property_update_notifier(prop, NC_NODE | NA_EDITED); +} + } // namespace blender::nodes::node_geo_set_curve_normal_cc void register_node_type_geo_set_curve_normal() @@ -72,4 +88,6 @@ void register_node_type_geo_set_curve_normal() ntype.draw_buttons = file_ns::node_layout; nodeRegisterType(&ntype); + + file_ns::node_rna(ntype.rna_ext.srna); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc index 7be1ad87522..485878fd515 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc @@ -16,6 +16,10 @@ #include "UI_interface.hh" #include "UI_resources.hh" +#include "RNA_enum_types.h" + +#include "NOD_rna_define.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_subdivision_surface_cc { @@ -190,6 +194,27 @@ static void node_geo_exec(GeoNodeExecParams params) params.set_output("Mesh", std::move(geometry_set)); } +static void node_rna(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "uv_smooth", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_node_storage(prop, uv_smooth); + RNA_def_property_enum_items(prop, rna_enum_subdivision_uv_smooth_items); + RNA_def_property_enum_default(prop, SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES); + RNA_def_property_ui_text(prop, "UV Smooth", "Controls how smoothing is applied to UVs"); + RNA_def_property_update_runtime(prop, (void *)rna_Node_update); + RNA_def_property_update_notifier(prop, NC_NODE | NA_EDITED); + + prop = RNA_def_property(srna, "boundary_smooth", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_node_storage(prop, boundary_smooth); + RNA_def_property_enum_items(prop, rna_enum_subdivision_boundary_smooth_items); + RNA_def_property_enum_default(prop, SUBSURF_BOUNDARY_SMOOTH_ALL); + RNA_def_property_ui_text(prop, "Boundary Smooth", "Controls how open boundaries are smoothed"); + RNA_def_property_update_runtime(prop, (void *)rna_Node_update); + RNA_def_property_update_notifier(prop, NC_NODE | NA_EDITED); +} + } // namespace blender::nodes::node_geo_subdivision_surface_cc void register_node_type_geo_subdivision_surface() @@ -210,4 +235,6 @@ void register_node_type_geo_subdivision_surface() node_free_standard_storage, node_copy_standard_storage); nodeRegisterType(&ntype); + + file_ns::node_rna(ntype.rna_ext.srna); }