Refactoring: Nodes: Dynamic declaration for dynamically-typed nodes #113553

Merged
Jacques Lucke merged 31 commits from mod_moder/blender:refacoring_node_declarations into main 2023-11-17 16:23:45 +01:00
19 changed files with 367 additions and 1264 deletions

View File

@ -29,7 +29,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 7
#define BLENDER_FILE_SUBVERSION 8
/* 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

View File

@ -95,6 +95,8 @@
#include "SEQ_sequencer.hh"
#include "SEQ_time.hh"
#include "NOD_socket.hh"
#include "versioning_common.hh"
static CLG_LogRef LOG = {"blo.readfile.doversion"};
@ -712,11 +714,11 @@ static void version_geometry_nodes_replace_transfer_attribute_node(bNodeTree *nt
sample_nearest_surface->locy = node->locy;
static auto socket_remap = []() {
Map<std::string, std::string> map;
map.add_new("Attribute", "Value_Vector");
map.add_new("Attribute_001", "Value_Float");
map.add_new("Attribute_002", "Value_Color");
map.add_new("Attribute_003", "Value_Bool");
map.add_new("Attribute_004", "Value_Int");
map.add_new("Attribute", "Value");
map.add_new("Attribute_001", "Value");
map.add_new("Attribute_002", "Value");
map.add_new("Attribute_003", "Value");
map.add_new("Attribute_004", "Value");
map.add_new("Source", "Mesh");
map.add_new("Source Position", "Sample Position");
return map;
@ -769,11 +771,11 @@ static void version_geometry_nodes_replace_transfer_attribute_node(bNodeTree *nt
static auto sample_index_remap = []() {
Map<std::string, std::string> map;
map.add_new("Attribute", "Value_Vector");
map.add_new("Attribute_001", "Value_Float");
map.add_new("Attribute_002", "Value_Color");
map.add_new("Attribute_003", "Value_Bool");
map.add_new("Attribute_004", "Value_Int");
map.add_new("Attribute", "Value");
map.add_new("Attribute_001", "Value");
map.add_new("Attribute_002", "Value");
map.add_new("Attribute_003", "Value");
map.add_new("Attribute_004", "Value");
map.add_new("Source Position", "Sample Position");
return map;
}();
@ -799,11 +801,11 @@ static void version_geometry_nodes_replace_transfer_attribute_node(bNodeTree *nt
const bool index_was_linked = nodeFindSocket(node, SOCK_IN, "Index")->link != nullptr;
static auto socket_remap = []() {
Map<std::string, std::string> map;
map.add_new("Attribute", "Value_Vector");
map.add_new("Attribute_001", "Value_Float");
map.add_new("Attribute_002", "Value_Color");
map.add_new("Attribute_003", "Value_Bool");
map.add_new("Attribute_004", "Value_Int");
map.add_new("Attribute", "Value");
map.add_new("Attribute_001", "Value");
map.add_new("Attribute_002", "Value");
map.add_new("Attribute_003", "Value");
map.add_new("Attribute_004", "Value");
map.add_new("Source", "Geometry");
map.add_new("Index", "Index");
return map;
@ -881,16 +883,13 @@ static void version_geometry_nodes_primitive_uv_maps(bNodeTree &ntree)
* releases and would make the file crash when trying to open it. */
storage.data_type = CD_PROP_FLOAT3;
blender::nodes::update_node_declaration_and_sockets(ntree, *store_attribute_node);
bNodeSocket *store_attribute_geometry_input = static_cast<bNodeSocket *>(
store_attribute_node->inputs.first);
bNodeSocket *store_attribute_name_input = store_attribute_geometry_input->next->next;
bNodeSocket *store_attribute_value_input = nullptr;
LISTBASE_FOREACH (bNodeSocket *, socket, &store_attribute_node->inputs) {
if (socket->type == SOCK_VECTOR) {
store_attribute_value_input = socket;
break;
}
}
bNodeSocket *store_attribute_value_input = store_attribute_geometry_input->next->next->next;
BLI_assert(store_attribute_value_input->type == SOCK_VECTOR);
bNodeSocket *store_attribute_geometry_output = static_cast<bNodeSocket *>(
store_attribute_node->outputs.first);
LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
@ -1017,7 +1016,7 @@ static void version_geometry_nodes_extrude_smooth_propagation(bNodeTree &ntree)
is_smooth_node,
nodeFindSocket(is_smooth_node, SOCK_OUT, "Smooth"),
capture_node,
nodeFindSocket(capture_node, SOCK_IN, "Value_003"));
nodeFindSocket(capture_node, SOCK_IN, "Value"));
nodeAddLink(&ntree,
capture_node,
nodeFindSocket(capture_node, SOCK_OUT, "Geometry"),
@ -1044,7 +1043,7 @@ static void version_geometry_nodes_extrude_smooth_propagation(bNodeTree &ntree)
}
nodeAddLink(&ntree,
capture_node,
nodeFindSocket(capture_node, SOCK_OUT, "Attribute_003"),
nodeFindSocket(capture_node, SOCK_OUT, "Attribute"),
set_smooth_node,
nodeFindSocket(set_smooth_node, SOCK_IN, "Shade Smooth"));
}

View File

@ -1237,6 +1237,61 @@ static void enable_geometry_nodes_is_modifier(Main &bmain)
}
}
static void version_socket_identifier_suffixes_for_dynamic_types(
ListBase sockets, const char *separator, const std::optional<int> total = std::nullopt)
{
int index = 0;
LISTBASE_FOREACH (bNodeSocket *, socket, &sockets) {
if (socket->is_available()) {
if (char *pos = strstr(socket->identifier, separator)) {
/* End the identifier at the separator so that the old suffix is ignored. */
*pos = '\0';
if (total.has_value()) {
index++;
if (index == *total) {
return;
}
}
}
}
else {
/* Rename existing identifiers so that they don't conflict with the renamed one. Those will
* be removed after versioning code. */
BLI_strncat(socket->identifier, "_deprecated", sizeof(socket->identifier));
}
}
}
static void versioning_nodes_dynamic_sockets(bNodeTree &ntree)
{
LISTBASE_FOREACH (bNode *, node, &ntree.nodes) {
switch (node->type) {
case GEO_NODE_ACCUMULATE_FIELD:
/* This node requires the extra `total` parameter, because the `Group Index` identifier
* also has a space in the name, that should not be treated as separator. */
version_socket_identifier_suffixes_for_dynamic_types(node->inputs, " ", 1);
version_socket_identifier_suffixes_for_dynamic_types(node->outputs, " ", 3);
break;
case GEO_NODE_CAPTURE_ATTRIBUTE:
case GEO_NODE_ATTRIBUTE_STATISTIC:
case GEO_NODE_BLUR_ATTRIBUTE:
case GEO_NODE_EVALUATE_AT_INDEX:
case GEO_NODE_EVALUATE_ON_DOMAIN:
case GEO_NODE_INPUT_NAMED_ATTRIBUTE:
case GEO_NODE_RAYCAST:
case GEO_NODE_SAMPLE_INDEX:
case GEO_NODE_SAMPLE_NEAREST_SURFACE:
case GEO_NODE_SAMPLE_UV_SURFACE:
case GEO_NODE_STORE_NAMED_ATTRIBUTE:
case GEO_NODE_VIEWER:
version_socket_identifier_suffixes_for_dynamic_types(node->inputs, "_");
version_socket_identifier_suffixes_for_dynamic_types(node->outputs, "_");
break;
}
}
}
static void versioning_grease_pencil_stroke_radii_scaling(GreasePencil *grease_pencil)
{
using namespace blender;
@ -1965,6 +2020,14 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 8)) {
LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
if (ntree->type != NTREE_GEOMETRY) {
continue;
}
versioning_nodes_dynamic_sockets(*ntree);
}
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -541,9 +541,15 @@ class NodeDeclarationBuilder {
BaseSocketDeclarationBuilder &add_input(eNodeSocketDatatype socket_type,
StringRef name,
StringRef identifier = "");
BaseSocketDeclarationBuilder &add_input(eCustomDataType data_type,
StringRef name,
StringRef identifier = "");
BaseSocketDeclarationBuilder &add_output(eNodeSocketDatatype socket_type,
StringRef name,
StringRef identifier = "");
BaseSocketDeclarationBuilder &add_output(eCustomDataType data_type,
StringRef name,
StringRef identifier = "");
aal::RelationsInNode &get_anonymous_attribute_relations()
{

View File

@ -24,59 +24,46 @@ NODE_STORAGE_FUNCS(NodeAccumulateField)
static void node_declare(NodeDeclarationBuilder &b)
{
std::string value_in_description = N_("The values to be accumulated");
std::string leading_out_description = N_(
"The running total of values in the corresponding group, starting at the first value");
std::string trailing_out_description = N_(
"The running total of values in the corresponding group, starting at zero");
std::string total_out_description = N_(
"The total of all of the values in the corresponding group");
const bNode *node = b.node_or_null();
if (node != nullptr) {
const eCustomDataType data_type = eCustomDataType(node_storage(*node).data_type);
BaseSocketDeclarationBuilder *value_declaration = nullptr;
switch (data_type) {
case CD_PROP_FLOAT3:
value_declaration = &b.add_input<decl::Vector>("Value").default_value({1.0f, 1.0f, 1.0f});
break;
mod_moder marked this conversation as resolved Outdated

missing break.

missing `break`.
case CD_PROP_FLOAT:
value_declaration = &b.add_input<decl::Float>("Value").default_value(1.0f);
break;
case CD_PROP_INT32:
value_declaration = &b.add_input<decl::Int>("Value").default_value(1);
break;
default:
BLI_assert_unreachable();
break;
}
value_declaration->supports_field().description(N_("The values to be accumulated"));
}
b.add_input<decl::Vector>("Value", "Value Vector")
.default_value({1.0f, 1.0f, 1.0f})
.supports_field()
.description(value_in_description);
b.add_input<decl::Float>("Value", "Value Float")
.default_value(1.0f)
.supports_field()
.description(value_in_description);
b.add_input<decl::Int>("Value", "Value Int")
.default_value(1)
.supports_field()
.description(value_in_description);
b.add_input<decl::Int>("Group ID", "Group Index")
.supports_field()
.description("An index used to group values together for multiple separate accumulations");
b.add_output<decl::Vector>("Leading", "Leading Vector")
.field_source_reference_all()
.description(leading_out_description);
b.add_output<decl::Float>("Leading", "Leading Float")
.field_source_reference_all()
.description(leading_out_description);
b.add_output<decl::Int>("Leading", "Leading Int")
.field_source_reference_all()
.description(leading_out_description);
b.add_output<decl::Vector>("Trailing", "Trailing Vector")
.field_source_reference_all()
.description(trailing_out_description);
b.add_output<decl::Float>("Trailing", "Trailing Float")
.field_source_reference_all()
.description(trailing_out_description);
b.add_output<decl::Int>("Trailing", "Trailing Int")
.field_source_reference_all()
.description(trailing_out_description);
b.add_output<decl::Vector>("Total", "Total Vector")
.field_source_reference_all()
.description(total_out_description);
b.add_output<decl::Float>("Total", "Total Float")
.field_source_reference_all()
.description(total_out_description);
b.add_output<decl::Int>("Total", "Total Int")
.field_source_reference_all()
.description(total_out_description);
if (node != nullptr) {
const eCustomDataType data_type = eCustomDataType(node_storage(*node).data_type);
b.add_output(data_type, "Leading")
.field_source_reference_all()
.description(N_("The running total of values in the corresponding group, starting at the "
"first value"));
b.add_output(data_type, "Trailing")
.field_source_reference_all()
.description(
N_("The running total of values in the corresponding group, starting at zero"));
b.add_output(data_type, "Total")
.field_source_reference_all()
.description(N_("The total of all of the values in the corresponding group"));
}
}
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
@ -93,43 +80,6 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
node->storage = data;
}
static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeAccumulateField &storage = node_storage(*node);
const eCustomDataType data_type = eCustomDataType(storage.data_type);
bNodeSocket *sock_in_vector = static_cast<bNodeSocket *>(node->inputs.first);
bNodeSocket *sock_in_float = sock_in_vector->next;
bNodeSocket *sock_in_int = sock_in_float->next;
bNodeSocket *sock_out_vector = static_cast<bNodeSocket *>(node->outputs.first);
bNodeSocket *sock_out_float = sock_out_vector->next;
bNodeSocket *sock_out_int = sock_out_float->next;
bNodeSocket *sock_out_first_vector = sock_out_int->next;
bNodeSocket *sock_out_first_float = sock_out_first_vector->next;
bNodeSocket *sock_out_first_int = sock_out_first_float->next;
bNodeSocket *sock_out_total_vector = sock_out_first_int->next;
bNodeSocket *sock_out_total_float = sock_out_total_vector->next;
bNodeSocket *sock_out_total_int = sock_out_total_float->next;
bke::nodeSetSocketAvailability(ntree, sock_in_vector, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, sock_in_float, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, sock_in_int, data_type == CD_PROP_INT32);
bke::nodeSetSocketAvailability(ntree, sock_out_vector, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, sock_out_float, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, sock_out_int, data_type == CD_PROP_INT32);
bke::nodeSetSocketAvailability(ntree, sock_out_first_vector, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, sock_out_first_float, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, sock_out_first_int, data_type == CD_PROP_INT32);
bke::nodeSetSocketAvailability(ntree, sock_out_total_vector, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, sock_out_total_float, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, sock_out_total_int, data_type == CD_PROP_INT32);
}
enum class AccumulationMode { Leading = 0, Trailing = 1 };
static std::optional<eCustomDataType> node_type_from_other_socket(const bNodeSocket &socket)
@ -150,6 +100,9 @@ static std::optional<eCustomDataType> node_type_from_other_socket(const bNodeSoc
static void node_gather_link_searches(GatherLinkSearchOpParams &params)
{
const NodeDeclaration &declaration = *params.node_type().static_declaration;
search_link_ops_for_declarations(params, declaration.inputs);
const std::optional<eCustomDataType> type = node_type_from_other_socket(params.other_socket());
if (!type) {
return;
@ -189,15 +142,6 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
params.update_and_connect_available_socket(node, "Value");
},
0);
params.add_item(
IFACE_("Group ID"),
[type](LinkSearchOpParams &params) {
bNode &node = params.add_node("GeometryNodeAccumulateField");
node_storage(node).data_type = *type;
params.update_and_connect_available_socket(node, "Group Index");
},
-1);
}
}
@ -395,50 +339,30 @@ class TotalFieldInput final : public bke::GeometryFieldInput {
}
};
template<typename T> std::string identifier_suffix()
{
if constexpr (std::is_same_v<T, int>) {
return "Int";
}
if constexpr (std::is_same_v<T, float>) {
return "Float";
}
if constexpr (std::is_same_v<T, float3>) {
return "Vector";
}
}
static void node_geo_exec(GeoNodeExecParams params)
{
const NodeAccumulateField &storage = node_storage(params.node());
const eCustomDataType data_type = eCustomDataType(storage.data_type);
const eAttrDomain source_domain = eAttrDomain(storage.domain);
Field<int> group_index_field = params.extract_input<Field<int>>("Group Index");
bke::attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
if constexpr (is_same_any_v<T, int, float, float3>) {
const std::string suffix = " " + identifier_suffix<T>();
GField input_field = params.extract_input<GField>("Value" + suffix);
if (params.output_is_required("Leading" + suffix)) {
params.set_output(
"Leading" + suffix,
Field<T>{std::make_shared<AccumulateFieldInput>(
source_domain, input_field, group_index_field, AccumulationMode::Leading)});
}
if (params.output_is_required("Trailing" + suffix)) {
params.set_output(
"Trailing" + suffix,
Field<T>{std::make_shared<AccumulateFieldInput>(
source_domain, input_field, group_index_field, AccumulationMode::Trailing)});
}
if (params.output_is_required("Total" + suffix)) {
params.set_output("Total" + suffix,
Field<T>{std::make_shared<TotalFieldInput>(
source_domain, input_field, group_index_field)});
}
}
});
const Field<int> group_index_field = params.extract_input<Field<int>>("Group Index");
const GField input_field = params.extract_input<GField>("Value");
if (params.output_is_required("Leading")) {
params.set_output<GField>(
"Leading",
GField{std::make_shared<AccumulateFieldInput>(
source_domain, input_field, group_index_field, AccumulationMode::Leading)});
}
if (params.output_is_required("Trailing")) {
params.set_output<GField>(
"Trailing",
GField{std::make_shared<AccumulateFieldInput>(
source_domain, input_field, group_index_field, AccumulationMode::Trailing)});
}
if (params.output_is_required("Total")) {
params.set_output<GField>(
"Total",
GField{std::make_shared<TotalFieldInput>(source_domain, input_field, group_index_field)});
}
}
static void node_rna(StructRNA *srna)
@ -475,7 +399,6 @@ static void node_register()
geo_node_type_base(&ntype, GEO_NODE_ACCUMULATE_FIELD, "Accumulate Field", NODE_CLASS_CONVERTER);
ntype.geometry_node_execute = node_geo_exec;
ntype.initfunc = node_init;
ntype.updatefunc = node_update;
ntype.draw_buttons = node_layout;
ntype.declare = node_declare;
ntype.gather_link_search_ops = node_gather_link_searches;

View File

@ -21,21 +21,19 @@ NODE_STORAGE_FUNCS(NodeGeometryAttributeCapture)
static void node_declare(NodeDeclarationBuilder &b)
{
const bNode *node = b.node_or_null();
b.add_input<decl::Geometry>("Geometry");
b.add_input<decl::Vector>("Value").field_on_all();
b.add_input<decl::Float>("Value", "Value_001").field_on_all();
b.add_input<decl::Color>("Value", "Value_002").field_on_all();
b.add_input<decl::Bool>("Value", "Value_003").field_on_all();
b.add_input<decl::Int>("Value", "Value_004").field_on_all();
b.add_input<decl::Rotation>("Value", "Value_005").field_on_all();
if (node != nullptr) {
const eCustomDataType data_type = eCustomDataType(node_storage(*node).data_type);
b.add_input(data_type, "Value").field_on_all();
}
b.add_output<decl::Geometry>("Geometry").propagate_all();
b.add_output<decl::Vector>("Attribute").field_on_all();
b.add_output<decl::Float>("Attribute", "Attribute_001").field_on_all();
b.add_output<decl::Color>("Attribute", "Attribute_002").field_on_all();
b.add_output<decl::Bool>("Attribute", "Attribute_003").field_on_all();
b.add_output<decl::Int>("Attribute", "Attribute_004").field_on_all();
b.add_output<decl::Rotation>("Attribute", "Attribute_005").field_on_all();
if (node != nullptr) {
const eCustomDataType data_type = eCustomDataType(node_storage(*node).data_type);
b.add_output(data_type, "Attribute").field_on_all();
}
}
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
@ -55,47 +53,11 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
node->storage = data;
}
static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryAttributeCapture &storage = node_storage(*node);
const eCustomDataType data_type = eCustomDataType(storage.data_type);
bNodeSocket *socket_value_geometry = static_cast<bNodeSocket *>(node->inputs.first);
bNodeSocket *socket_value_vector = socket_value_geometry->next;
bNodeSocket *socket_value_float = socket_value_vector->next;
bNodeSocket *socket_value_color4f = socket_value_float->next;
bNodeSocket *socket_value_boolean = socket_value_color4f->next;
bNodeSocket *socket_value_int32 = socket_value_boolean->next;
bNodeSocket *socket_value_quat = socket_value_int32->next;
bke::nodeSetSocketAvailability(ntree, socket_value_vector, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, socket_value_float, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, socket_value_color4f, data_type == CD_PROP_COLOR);
bke::nodeSetSocketAvailability(ntree, socket_value_boolean, data_type == CD_PROP_BOOL);
bke::nodeSetSocketAvailability(ntree, socket_value_int32, data_type == CD_PROP_INT32);
bke::nodeSetSocketAvailability(ntree, socket_value_quat, data_type == CD_PROP_QUATERNION);
bNodeSocket *out_socket_value_geometry = static_cast<bNodeSocket *>(node->outputs.first);
bNodeSocket *out_socket_value_vector = out_socket_value_geometry->next;
bNodeSocket *out_socket_value_float = out_socket_value_vector->next;
bNodeSocket *out_socket_value_color4f = out_socket_value_float->next;
bNodeSocket *out_socket_value_boolean = out_socket_value_color4f->next;
bNodeSocket *out_socket_value_int32 = out_socket_value_boolean->next;
bNodeSocket *out_socket_value_quat = out_socket_value_int32->next;
bke::nodeSetSocketAvailability(ntree, out_socket_value_vector, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, out_socket_value_float, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, out_socket_value_color4f, data_type == CD_PROP_COLOR);
bke::nodeSetSocketAvailability(ntree, out_socket_value_boolean, data_type == CD_PROP_BOOL);
bke::nodeSetSocketAvailability(ntree, out_socket_value_int32, data_type == CD_PROP_INT32);
bke::nodeSetSocketAvailability(ntree, out_socket_value_quat, data_type == CD_PROP_QUATERNION);
}
static void node_gather_link_searches(GatherLinkSearchOpParams &params)
{
const NodeDeclaration &declaration = *params.node_type().static_declaration;
search_link_ops_for_declarations(params, declaration.inputs.as_span().take_front(1));
search_link_ops_for_declarations(params, declaration.outputs.as_span().take_front(1));
search_link_ops_for_declarations(params, declaration.inputs);
search_link_ops_for_declarations(params, declaration.outputs);
const bNodeType &node_type = params.node_type();
const std::optional<eCustomDataType> type = bke::socket_type_to_custom_data_type(
@ -147,27 +109,6 @@ static void clean_unused_attributes(const AnonymousAttributePropagationInfo &pro
}
}
static StringRefNull identifier_suffix(eCustomDataType data_type)
{
switch (data_type) {
case CD_PROP_FLOAT:
return "_001";
case CD_PROP_INT32:
return "_004";
case CD_PROP_QUATERNION:
return "_005";
case CD_PROP_COLOR:
return "_002";
case CD_PROP_BOOL:
return "_003";
case CD_PROP_FLOAT3:
return "";
default:
BLI_assert_unreachable();
return "";
}
}
static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
@ -181,44 +122,17 @@ static void node_geo_exec(GeoNodeExecParams params)
}
const NodeGeometryAttributeCapture &storage = node_storage(params.node());
const eCustomDataType data_type = eCustomDataType(storage.data_type);
const eAttrDomain domain = eAttrDomain(storage.domain);
const std::string output_identifier = "Attribute" + identifier_suffix(data_type);
AnonymousAttributeIDPtr attribute_id = params.get_output_anonymous_attribute_id_if_needed(
output_identifier);
"Attribute");
if (!attribute_id) {
params.set_output("Geometry", geometry_set);
params.set_default_remaining_outputs();
return;
}
const std::string input_identifier = "Value" + identifier_suffix(data_type);
GField field;
switch (data_type) {
case CD_PROP_FLOAT:
field = params.extract_input<GField>(input_identifier);
break;
case CD_PROP_FLOAT3:
field = params.extract_input<GField>(input_identifier);
break;
case CD_PROP_COLOR:
field = params.extract_input<GField>(input_identifier);
break;
case CD_PROP_BOOL:
field = params.extract_input<GField>(input_identifier);
break;
case CD_PROP_INT32:
field = params.extract_input<GField>(input_identifier);
break;
case CD_PROP_QUATERNION:
field = params.extract_input<GField>(input_identifier);
break;
default:
break;
}
const GField field = params.extract_input<GField>("Value");
const auto capture_on = [&](GeometryComponent &component) {
bke::try_capture_field_on_geometry(component, *attribute_id, domain, field);
@ -284,7 +198,6 @@ static void node_register()
node_free_standard_storage,
node_copy_standard_storage);
ntype.initfunc = node_init;
ntype.updatefunc = node_update;
ntype.declare = node_declare;
ntype.geometry_node_execute = node_geo_exec;
ntype.draw_buttons = node_layout;

View File

@ -23,28 +23,24 @@ namespace blender::nodes::node_geo_attribute_statistic_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
const bNode *node = b.node_or_null();
b.add_input<decl::Geometry>("Geometry");
b.add_input<decl::Bool>("Selection").default_value(true).field_on_all().hide_value();
b.add_input<decl::Float>("Attribute").hide_value().field_on_all();
b.add_input<decl::Vector>("Attribute", "Attribute_001").hide_value().field_on_all();
b.add_output<decl::Float>("Mean");
b.add_output<decl::Float>("Median");
b.add_output<decl::Float>("Sum");
b.add_output<decl::Float>("Min");
b.add_output<decl::Float>("Max");
b.add_output<decl::Float>("Range");
b.add_output<decl::Float>("Standard Deviation");
b.add_output<decl::Float>("Variance");
if (node != nullptr) {
const eCustomDataType data_type = eCustomDataType(node->custom1);
b.add_input(data_type, "Attribute").hide_value().field_on_all();
b.add_output<decl::Vector>("Mean", "Mean_001");
b.add_output<decl::Vector>("Median", "Median_001");
b.add_output<decl::Vector>("Sum", "Sum_001");
b.add_output<decl::Vector>("Min", "Min_001");
b.add_output<decl::Vector>("Max", "Max_001");
b.add_output<decl::Vector>("Range", "Range_001");
b.add_output<decl::Vector>("Standard Deviation", "Standard Deviation_001");
b.add_output<decl::Vector>("Variance", "Variance_001");
b.add_output(data_type, "Mean");
b.add_output(data_type, "Median");
b.add_output(data_type, "Sum");
b.add_output(data_type, "Min");
b.add_output(data_type, "Max");
b.add_output(data_type, "Range");
b.add_output(data_type, "Standard Deviation");
b.add_output(data_type, "Variance");
}
}
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
@ -59,54 +55,6 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
node->custom2 = ATTR_DOMAIN_POINT;
}
static void node_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *socket_geo = static_cast<bNodeSocket *>(node->inputs.first);
bNodeSocket *socket_selection = socket_geo->next;
bNodeSocket *socket_float_attr = socket_selection->next;
bNodeSocket *socket_float3_attr = socket_float_attr->next;
bNodeSocket *socket_float_mean = static_cast<bNodeSocket *>(node->outputs.first);
bNodeSocket *socket_float_median = socket_float_mean->next;
bNodeSocket *socket_float_sum = socket_float_median->next;
bNodeSocket *socket_float_min = socket_float_sum->next;
bNodeSocket *socket_float_max = socket_float_min->next;
bNodeSocket *socket_float_range = socket_float_max->next;
bNodeSocket *socket_float_std = socket_float_range->next;
bNodeSocket *socket_float_variance = socket_float_std->next;
bNodeSocket *socket_vector_mean = socket_float_variance->next;
bNodeSocket *socket_vector_median = socket_vector_mean->next;
bNodeSocket *socket_vector_sum = socket_vector_median->next;
bNodeSocket *socket_vector_min = socket_vector_sum->next;
bNodeSocket *socket_vector_max = socket_vector_min->next;
bNodeSocket *socket_vector_range = socket_vector_max->next;
bNodeSocket *socket_vector_std = socket_vector_range->next;
bNodeSocket *socket_vector_variance = socket_vector_std->next;
const eCustomDataType data_type = eCustomDataType(node->custom1);
bke::nodeSetSocketAvailability(ntree, socket_float_attr, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, socket_float_mean, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, socket_float_median, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, socket_float_sum, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, socket_float_min, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, socket_float_max, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, socket_float_range, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, socket_float_std, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, socket_float_variance, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, socket_float3_attr, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, socket_vector_mean, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, socket_vector_median, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, socket_vector_sum, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, socket_vector_min, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, socket_vector_max, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, socket_vector_range, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, socket_vector_std, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, socket_vector_variance, data_type == CD_PROP_FLOAT3);
}
static std::optional<eCustomDataType> node_type_from_other_socket(const bNodeSocket &socket)
{
switch (socket.type) {
@ -126,7 +74,7 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
{
const bNodeType &node_type = params.node_type();
const NodeDeclaration &declaration = *params.node_type().static_declaration;
search_link_ops_for_declarations(params, declaration.inputs.as_span().take_front(2));
search_link_ops_for_declarations(params, declaration.inputs);
const std::optional<eCustomDataType> type = node_type_from_other_socket(params.other_socket());
if (!type) {
@ -278,7 +226,7 @@ static void node_geo_exec(GeoNodeExecParams params)
break;
}
case CD_PROP_FLOAT3: {
const Field<float3> input_field = params.get_input<Field<float3>>("Attribute_001");
const Field<float3> input_field = params.get_input<Field<float3>>("Attribute");
Vector<float3> data;
for (const GeometryComponent *component : components) {
const std::optional<AttributeAccessor> attributes = component->attributes();
@ -310,14 +258,14 @@ static void node_geo_exec(GeoNodeExecParams params)
float3 mean{0};
float3 variance{0};
float3 standard_deviation{0};
const bool sort_required = params.output_is_required("Min_001") ||
params.output_is_required("Max_001") ||
params.output_is_required("Range_001") ||
params.output_is_required("Median_001");
const bool sum_required = params.output_is_required("Sum_001") ||
params.output_is_required("Mean_001");
const bool variance_required = params.output_is_required("Standard Deviation_001") ||
params.output_is_required("Variance_001");
const bool sort_required = params.output_is_required("Min") ||
params.output_is_required("Max") ||
params.output_is_required("Range") ||
params.output_is_required("Median");
const bool sum_required = params.output_is_required("Sum") ||
params.output_is_required("Mean");
const bool variance_required = params.output_is_required("Standard Deviation") ||
params.output_is_required("Variance");
Array<float> data_x;
Array<float> data_y;
@ -364,18 +312,18 @@ static void node_geo_exec(GeoNodeExecParams params)
}
if (sum_required) {
params.set_output("Sum_001", sum);
params.set_output("Mean_001", mean);
params.set_output("Sum", sum);
params.set_output("Mean", mean);
}
if (sort_required) {
params.set_output("Min_001", min);
params.set_output("Max_001", max);
params.set_output("Range_001", range);
params.set_output("Median_001", median);
params.set_output("Min", min);
params.set_output("Max", max);
params.set_output("Range", range);
params.set_output("Median", median);
}
if (variance_required) {
params.set_output("Standard Deviation_001", standard_deviation);
params.set_output("Variance_001", variance);
params.set_output("Standard Deviation", standard_deviation);
params.set_output("Variance", variance);
}
break;
}
@ -418,9 +366,8 @@ static void node_register()
geo_node_type_base(
&ntype, GEO_NODE_ATTRIBUTE_STATISTIC, "Attribute Statistic", NODE_CLASS_ATTRIBUTE);
ntype.declare = node_declare;
ntype.initfunc = node_init;
ntype.updatefunc = node_update;
ntype.declare = node_declare;
ntype.geometry_node_execute = node_geo_exec;
ntype.draw_buttons = node_layout;
ntype.gather_link_search_ops = node_gather_link_searches;

View File

@ -36,23 +36,12 @@ namespace blender::nodes::node_geo_blur_attribute_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Float>("Value", "Value_Float")
.supports_field()
.hide_value()
.is_default_link_socket();
b.add_input<decl::Int>("Value", "Value_Int")
.supports_field()
.hide_value()
.is_default_link_socket();
b.add_input<decl::Vector>("Value", "Value_Vector")
.supports_field()
.hide_value()
.is_default_link_socket();
b.add_input<decl::Color>("Value", "Value_Color")
.supports_field()
.hide_value()
.is_default_link_socket();
const bNode *node = b.node_or_null();
if (node != nullptr) {
const eCustomDataType data_type = eCustomDataType(node->custom1);
b.add_input(data_type, "Value").supports_field().hide_value().is_default_link_socket();
}
b.add_input<decl::Int>("Iterations")
.default_value(1)
.min(0)
@ -65,12 +54,10 @@ static void node_declare(NodeDeclarationBuilder &b)
.supports_field()
.description("Relative mix weight of neighboring elements");
b.add_output<decl::Float>("Value", "Value_Float").field_source_reference_all().dependent_field();
b.add_output<decl::Int>("Value", "Value_Int").field_source_reference_all().dependent_field();
b.add_output<decl::Vector>("Value", "Value_Vector")
.field_source_reference_all()
.dependent_field();
b.add_output<decl::Color>("Value", "Value_Color").field_source_reference_all().dependent_field();
if (node != nullptr) {
const eCustomDataType data_type = eCustomDataType(node->custom1);
b.add_output(data_type, "Value").field_source_reference_all().dependent_field();
}
}
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
@ -89,7 +76,7 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
const NodeDeclaration &declaration = *node_type.static_declaration;
/* Weight and Iterations inputs don't change based on the data type. */
search_link_ops_for_declarations(params, declaration.inputs.as_span().take_back(2));
search_link_ops_for_declarations(params, declaration.inputs);
const std::optional<eCustomDataType> new_node_type = bke::socket_type_to_custom_data_type(
eNodeSocketDatatype(params.other_socket().type));
@ -115,31 +102,6 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
});
}
static void node_update(bNodeTree *ntree, bNode *node)
{
const eCustomDataType data_type = static_cast<eCustomDataType>(node->custom1);
bNodeSocket *socket_value_float = (bNodeSocket *)node->inputs.first;
bNodeSocket *socket_value_int32 = socket_value_float->next;
bNodeSocket *socket_value_vector = socket_value_int32->next;
bNodeSocket *socket_value_color4f = socket_value_vector->next;
bke::nodeSetSocketAvailability(ntree, socket_value_float, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, socket_value_int32, data_type == CD_PROP_INT32);
bke::nodeSetSocketAvailability(ntree, socket_value_vector, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, socket_value_color4f, data_type == CD_PROP_COLOR);
bNodeSocket *out_socket_value_float = (bNodeSocket *)node->outputs.first;
bNodeSocket *out_socket_value_int32 = out_socket_value_float->next;
bNodeSocket *out_socket_value_vector = out_socket_value_int32->next;
bNodeSocket *out_socket_value_color4f = out_socket_value_vector->next;
bke::nodeSetSocketAvailability(ntree, out_socket_value_float, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, out_socket_value_int32, data_type == CD_PROP_INT32);
bke::nodeSetSocketAvailability(ntree, out_socket_value_vector, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, out_socket_value_color4f, data_type == CD_PROP_COLOR);
}
static void build_vert_to_vert_by_edge_map(const Span<int2> edges,
const int verts_num,
Array<int> &r_offsets,
@ -494,38 +456,15 @@ class BlurAttributeFieldInput final : public bke::GeometryFieldInput {
}
};
static StringRefNull identifier_suffix(eCustomDataType data_type)
{
switch (data_type) {
case CD_PROP_FLOAT:
return "Float";
case CD_PROP_INT32:
return "Int";
case CD_PROP_COLOR:
return "Color";
case CD_PROP_FLOAT3:
return "Vector";
default:
BLI_assert_unreachable();
return "";
}
}
static void node_geo_exec(GeoNodeExecParams params)
{
const eCustomDataType data_type = static_cast<eCustomDataType>(params.node().custom1);
const int iterations = params.extract_input<int>("Iterations");
Field<float> weight_field = params.extract_input<Field<float>>("Weight");
bke::attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
static const std::string identifier = "Value_" + identifier_suffix(data_type);
Field<T> value_field = params.extract_input<Field<T>>(identifier);
Field<T> output_field{std::make_shared<BlurAttributeFieldInput>(
std::move(weight_field), std::move(value_field), iterations)};
params.set_output(identifier, std::move(output_field));
});
GField value_field = params.extract_input<GField>("Value");
GField output_field{std::make_shared<BlurAttributeFieldInput>(
std::move(weight_field), std::move(value_field), iterations)};
params.set_output<GField>("Value", std::move(output_field));
}
static void node_rna(StructRNA *srna)
@ -550,9 +489,8 @@ static void node_register()
{
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_BLUR_ATTRIBUTE, "Blur Attribute", NODE_CLASS_ATTRIBUTE);
ntype.declare = node_declare;
ntype.initfunc = node_init;
ntype.updatefunc = node_update;
ntype.declare = node_declare;
ntype.draw_buttons = node_layout;
ntype.geometry_node_execute = node_geo_exec;
ntype.gather_link_search_ops = node_gather_link_searches;

View File

@ -59,21 +59,15 @@ namespace blender::nodes::node_geo_evaluate_at_index_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
const bNode *node = b.node_or_null();
b.add_input<decl::Int>("Index").min(0).supports_field();
if (node != nullptr) {
const eCustomDataType data_type = eCustomDataType(node->custom2);
b.add_input(data_type, "Value").hide_value().supports_field();
b.add_input<decl::Float>("Value", "Value_Float").hide_value().supports_field();
b.add_input<decl::Int>("Value", "Value_Int").hide_value().supports_field();
b.add_input<decl::Vector>("Value", "Value_Vector").hide_value().supports_field();
b.add_input<decl::Color>("Value", "Value_Color").hide_value().supports_field();
b.add_input<decl::Bool>("Value", "Value_Bool").hide_value().supports_field();
b.add_input<decl::Rotation>("Value", "Value_Rotation").hide_value().supports_field();
b.add_output<decl::Float>("Value", "Value_Float").field_source_reference_all();
b.add_output<decl::Int>("Value", "Value_Int").field_source_reference_all();
b.add_output<decl::Vector>("Value", "Value_Vector").field_source_reference_all();
b.add_output<decl::Color>("Value", "Value_Color").field_source_reference_all();
b.add_output<decl::Bool>("Value", "Value_Bool").field_source_reference_all();
b.add_output<decl::Rotation>("Value", "Value_Rotation").field_source_reference_all();
b.add_output(data_type, "Value").field_source_reference_all();
}
}
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
@ -88,40 +82,6 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
node->custom2 = CD_PROP_FLOAT;
}
static void node_update(bNodeTree *ntree, bNode *node)
{
const eCustomDataType data_type = eCustomDataType(node->custom2);
bNodeSocket *sock_index = static_cast<bNodeSocket *>(node->inputs.first);
bNodeSocket *sock_in_float = sock_index->next;
bNodeSocket *sock_in_int = sock_in_float->next;
bNodeSocket *sock_in_vector = sock_in_int->next;
bNodeSocket *sock_in_color = sock_in_vector->next;
bNodeSocket *sock_in_bool = sock_in_color->next;
bNodeSocket *sock_in_quat = sock_in_bool->next;
bNodeSocket *sock_out_float = static_cast<bNodeSocket *>(node->outputs.first);
bNodeSocket *sock_out_int = sock_out_float->next;
bNodeSocket *sock_out_vector = sock_out_int->next;
bNodeSocket *sock_out_color = sock_out_vector->next;
bNodeSocket *sock_out_bool = sock_out_color->next;
bNodeSocket *sock_out_quat = sock_out_bool->next;
bke::nodeSetSocketAvailability(ntree, sock_in_float, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, sock_in_int, data_type == CD_PROP_INT32);
bke::nodeSetSocketAvailability(ntree, sock_in_vector, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, sock_in_color, data_type == CD_PROP_COLOR);
bke::nodeSetSocketAvailability(ntree, sock_in_bool, data_type == CD_PROP_BOOL);
bke::nodeSetSocketAvailability(ntree, sock_in_quat, data_type == CD_PROP_QUATERNION);
bke::nodeSetSocketAvailability(ntree, sock_out_float, data_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, sock_out_int, data_type == CD_PROP_INT32);
bke::nodeSetSocketAvailability(ntree, sock_out_vector, data_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, sock_out_color, data_type == CD_PROP_COLOR);
bke::nodeSetSocketAvailability(ntree, sock_out_bool, data_type == CD_PROP_BOOL);
bke::nodeSetSocketAvailability(ntree, sock_out_quat, data_type == CD_PROP_QUATERNION);
}
static void node_gather_link_searches(GatherLinkSearchOpParams &params)
{
const bNodeType &node_type = params.node_type();
@ -144,42 +104,14 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
}
}
static StringRefNull identifier_suffix(eCustomDataType data_type)
{
switch (data_type) {
case CD_PROP_BOOL:
return "Bool";
case CD_PROP_FLOAT:
return "Float";
case CD_PROP_INT32:
return "Int";
case CD_PROP_COLOR:
return "Color";
case CD_PROP_FLOAT3:
return "Vector";
case CD_PROP_QUATERNION:
return "Rotation";
default:
BLI_assert_unreachable();
return "";
}
}
static void node_geo_exec(GeoNodeExecParams params)
{
const bNode &node = params.node();
const eAttrDomain domain = eAttrDomain(node.custom1);
const eCustomDataType data_type = eCustomDataType(node.custom2);
bke::attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
static const std::string identifier = "Value_" + identifier_suffix(data_type);
Field<T> output_field{
std::make_shared<EvaluateAtIndexInput>(params.extract_input<Field<int>>("Index"),
params.extract_input<Field<T>>(identifier),
domain)};
params.set_output(identifier, std::move(output_field));
});
GField output_field{std::make_shared<EvaluateAtIndexInput>(
params.extract_input<Field<int>>("Index"), params.extract_input<GField>("Value"), domain)};
params.set_output<GField>("Value", std::move(output_field));
}
static void node_rna(StructRNA *srna)
@ -210,10 +142,9 @@ static void node_register()
geo_node_type_base(
&ntype, GEO_NODE_EVALUATE_AT_INDEX, "Evaluate at Index", NODE_CLASS_CONVERTER);
ntype.geometry_node_execute = node_geo_exec;
ntype.declare = node_declare;
ntype.draw_buttons = node_layout;
ntype.initfunc = node_init;
ntype.updatefunc = node_update;
ntype.declare = node_declare;
ntype.gather_link_search_ops = node_gather_link_searches;
nodeRegisterType(&ntype);

View File

@ -22,19 +22,14 @@ namespace blender::nodes::node_geo_evaluate_on_domain_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Float>("Value", "Value_Float").supports_field();
b.add_input<decl::Int>("Value", "Value_Int").supports_field();
b.add_input<decl::Vector>("Value", "Value_Vector").supports_field();
b.add_input<decl::Color>("Value", "Value_Color").supports_field();
b.add_input<decl::Bool>("Value", "Value_Bool").supports_field();
b.add_input<decl::Rotation>("Value", "Value_Rotation").supports_field();
const bNode *node = b.node_or_null();
b.add_output<decl::Float>("Value", "Value_Float").field_source_reference_all();
b.add_output<decl::Int>("Value", "Value_Int").field_source_reference_all();
b.add_output<decl::Vector>("Value", "Value_Vector").field_source_reference_all();
b.add_output<decl::Color>("Value", "Value_Color").field_source_reference_all();
b.add_output<decl::Bool>("Value", "Value_Bool").field_source_reference_all();
b.add_output<decl::Rotation>("Value", "Value_Rotation").field_source_reference_all();
if (node != nullptr) {
const eCustomDataType data_type = eCustomDataType(node->custom2);
b.add_input(data_type, "Value").supports_field();
b.add_output(data_type, "Value").field_source_reference_all();
}
}
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
@ -49,39 +44,6 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
node->custom2 = CD_PROP_FLOAT;
}