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
This commit is contained in:
Jacques Lucke 2023-08-09 12:47:58 +02:00
parent c61aa42f7d
commit f7c0ef1f73
9 changed files with 139 additions and 70 deletions

View File

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

View File

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

View File

@ -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<bNodeTree *>(ptr->owner_id);
bNode *node = static_cast<bNode *>(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;

View File

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

View File

@ -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<const bNode *>(ptr->data); \
return node_storage(node).member; \
}, \
[](PointerRNA *ptr, PropertyRNA * /*prop*/, const int value) { \
bNode &node = *static_cast<bNode *>(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<const bNode *>(ptr->data); \
return node.member; \
}, \
[](PointerRNA *ptr, PropertyRNA * /*prop*/, const int value) { \
bNode &node = *static_cast<bNode *>(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);

View File

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

View File

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

View File

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

View File

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