diff --git a/source/blender/blenkernel/intern/cpp_types.cc b/source/blender/blenkernel/intern/cpp_types.cc index 3736e90c304..3feeb0f2a1f 100644 --- a/source/blender/blenkernel/intern/cpp_types.cc +++ b/source/blender/blenkernel/intern/cpp_types.cc @@ -14,6 +14,7 @@ #include "NOD_geometry_nodes_bundle.hh" #include "NOD_geometry_nodes_closure.hh" #include "NOD_geometry_nodes_list.hh" +#include "NOD_geometry_nodes_values.hh" #include "DNA_meshdata_types.h" @@ -40,6 +41,8 @@ BLI_CPP_TYPE_MAKE(blender::nodes::ListPtr, CPPTypeFlags::None); BLI_CPP_TYPE_MAKE(blender::bke::GeometryNodesReferenceSet, CPPTypeFlags::None); BLI_CPP_TYPE_MAKE(blender::bke::SocketValueVariant, CPPTypeFlags::Printable); BLI_VECTOR_CPP_TYPE_MAKE(blender::bke::SocketValueVariant); +BLI_CPP_TYPE_MAKE(blender::nodes::GeoNodesMultiInput, + CPPTypeFlags::None); void BKE_cpp_types_init() { @@ -64,4 +67,5 @@ void BKE_cpp_types_init() BLI_CPP_TYPE_REGISTER(blender::bke::GeometryNodesReferenceSet); BLI_CPP_TYPE_REGISTER(blender::bke::SocketValueVariant); BLI_VECTOR_CPP_TYPE_REGISTER(blender::bke::SocketValueVariant); + BLI_CPP_TYPE_REGISTER(blender::nodes::GeoNodesMultiInput); } diff --git a/source/blender/blenlib/BLI_vector.hh b/source/blender/blenlib/BLI_vector.hh index d37b6de0347..86b27cad2e3 100644 --- a/source/blender/blenlib/BLI_vector.hh +++ b/source/blender/blenlib/BLI_vector.hh @@ -1151,4 +1151,8 @@ class Vector { template using RawVector = Vector; +template static constexpr bool is_Vector_v = false; +template +static constexpr bool is_Vector_v> = true; + } /* namespace blender */ diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index 67907e313d1..4de2e4fe9f5 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -105,27 +105,42 @@ class GeoNodeExecParams { */ template T extract_input(StringRef identifier) { - if constexpr (std::is_enum_v) { - return T(this->extract_input(identifier)); - } - else if constexpr (geo_nodes_type_stored_as_SocketValueVariant_v) { - SocketValueVariant value_variant = this->extract_input(identifier); - return value_variant.extract(); +#ifndef NDEBUG + this->check_input_access(identifier); +#endif + const int index = this->get_input_index(identifier); + if constexpr (is_GeoNodesMultiInput_v) { + using ValueT = typename T::value_type; + BLI_assert(node_.input_by_identifier(identifier)->is_multi_input()); + if constexpr (std::is_same_v) { + return params_.extract_input(index); + } + else { + auto values_variants = params_.extract_input>( + index); + GeoNodesMultiInput values; + values.values.reserve(values_variants.values.size()); + for (const int i : values_variants.values.index_range()) { + values.values.append(values_variants.values[i].extract()); + } + return values; + } } else { -#ifndef NDEBUG - this->check_input_access(identifier, &CPPType::get()); -#endif - const int index = this->get_input_index(identifier); - T value = params_.extract_input(index); - if constexpr (std::is_same_v) { - this->check_input_geometry_set(identifier, value); - } + SocketValueVariant value_variant = params_.extract_input(index); if constexpr (std::is_same_v) { - BLI_assert(value.valid_for_socket( - eNodeSocketDatatype(node_.input_by_identifier(identifier)->type))); + return value_variant; + } + else if constexpr (std::is_enum_v) { + return T(value_variant.extract()); + } + else { + T value = value_variant.extract(); + if constexpr (std::is_same_v) { + this->check_input_geometry_set(identifier, value); + } + return value; } - return value; } } @@ -137,27 +152,40 @@ class GeoNodeExecParams { */ template T get_input(StringRef identifier) const { - if constexpr (std::is_enum_v) { - return T(this->get_input(identifier)); - } - else if constexpr (geo_nodes_type_stored_as_SocketValueVariant_v) { - auto value_variant = this->get_input(identifier); - return value_variant.extract(); +#ifndef NDEBUG + this->check_input_access(identifier); +#endif + const int index = this->get_input_index(identifier); + if constexpr (is_GeoNodesMultiInput_v) { + using ValueT = typename T::value_type; + BLI_assert(node_.input_by_identifier(identifier)->is_multi_input()); + if constexpr (std::is_same_v) { + return params_.get_input(index); + } + else { + auto values_variants = params_.get_input>(index); + Vector values(values_variants.values.size()); + for (const int i : values_variants.values.index_range()) { + values[i] = values_variants.values[i].extract(); + } + return values; + } } else { -#ifndef NDEBUG - this->check_input_access(identifier, &CPPType::get()); -#endif - const int index = this->get_input_index(identifier); - const T &value = params_.get_input(index); - if constexpr (std::is_same_v) { - this->check_input_geometry_set(identifier, value); - } + const SocketValueVariant &value_variant = params_.get_input(index); if constexpr (std::is_same_v) { - BLI_assert(value.valid_for_socket( - eNodeSocketDatatype(node_.input_by_identifier(identifier)->type))); + return value_variant; + } + else if constexpr (std::is_enum_v) { + return T(value_variant.get()); + } + else { + T value = value_variant.get(); + if constexpr (std::is_same_v) { + this->check_input_geometry_set(identifier, value); + } + return value; } - return value; } } @@ -177,23 +205,18 @@ class GeoNodeExecParams { template void set_output(StringRef identifier, T &&value) { using StoredT = std::decay_t; - if constexpr (geo_nodes_type_stored_as_SocketValueVariant_v) { - this->set_output(identifier, SocketValueVariant::From(std::forward(value))); +#ifndef NDEBUG + this->check_output_access(identifier); +#endif + if constexpr (std::is_same_v) { + this->check_output_geometry_set(value); + } + const int index = this->get_output_index(identifier); + if constexpr (std::is_same_v) { + params_.set_output(index, std::forward(value)); } else { -#ifndef NDEBUG - const CPPType &type = CPPType::get(); - this->check_output_access(identifier, type); - if constexpr (std::is_same_v) { - BLI_assert(value.valid_for_socket( - eNodeSocketDatatype(node_.output_by_identifier(identifier)->type))); - } -#endif - if constexpr (std::is_same_v) { - this->check_output_geometry_set(value); - } - const int index = this->get_output_index(identifier); - params_.set_output(index, std::forward(value)); + params_.set_output(index, SocketValueVariant::From(std::forward(value))); } } @@ -315,8 +338,8 @@ class GeoNodeExecParams { private: /* Utilities for detecting common errors at when using this class. */ - void check_input_access(StringRef identifier, const CPPType *requested_type = nullptr) const; - void check_output_access(StringRef identifier, const CPPType &value_type) const; + void check_input_access(StringRef identifier) const; + void check_output_access(StringRef identifier) const; /* Find the active socket with the input name (not the identifier). */ const bNodeSocket *find_available_socket(const StringRef name) const; diff --git a/source/blender/nodes/NOD_geometry_nodes_bundle.hh b/source/blender/nodes/NOD_geometry_nodes_bundle.hh index a6a7907bddf..06e9f79abb9 100644 --- a/source/blender/nodes/NOD_geometry_nodes_bundle.hh +++ b/source/blender/nodes/NOD_geometry_nodes_bundle.hh @@ -128,40 +128,19 @@ inline std::optional BundleItemValue::as_socket_value( } converted_value = buffer; } - if constexpr (geo_nodes_type_stored_as_SocketValueVariant_v) { - const auto &value_variant = *static_cast(converted_value); - return value_variant.get(); - } - return *static_cast(converted_value); -} - -template constexpr bool is_valid_static_bundle_item_type() -{ - if (geo_nodes_is_field_base_type_v) { - return true; - } - if constexpr (fn::is_field_v) { - return geo_nodes_is_field_base_type_v; - } - if constexpr (is_same_any_v) { - return true; - } - return !geo_nodes_type_stored_as_SocketValueVariant_v; + const auto &value_variant = *static_cast(converted_value); + return value_variant.get(); } template inline const bke::bNodeSocketType *socket_type_info_by_static_type() { if constexpr (fn::is_field_v) { - if constexpr (geo_nodes_is_field_base_type_v) { - const std::optional socket_type = - bke::geo_nodes_base_cpp_type_to_socket_type(CPPType::get()); - BLI_assert(socket_type); - const bke::bNodeSocketType *socket_type_info = bke::node_socket_type_find_static( - *socket_type); - BLI_assert(socket_type_info); - return socket_type_info; - } - return nullptr; + const std::optional socket_type = + bke::geo_nodes_base_cpp_type_to_socket_type(CPPType::get()); + BLI_assert(socket_type); + const bke::bNodeSocketType *socket_type_info = bke::node_socket_type_find_static(*socket_type); + BLI_assert(socket_type_info); + return socket_type_info; } else { const std::optional socket_type = @@ -185,7 +164,6 @@ template constexpr bool is_valid_internal_bundle_item_type() template inline std::optional BundleItemValue::as() const { - static_assert(is_valid_static_bundle_item_type() || is_valid_internal_bundle_item_type()); if constexpr (is_valid_internal_bundle_item_type()) { using SharingInfoT = typename T::element_type; const auto *internal_value = std::get_if(&this->value); @@ -246,9 +224,6 @@ template inline std::optional Bundle::lookup_path(const StringRef template inline void to_stored_type(T &&value, Fn &&fn) { using DecayT = std::decay_t; - static_assert( - is_valid_static_bundle_item_type() || is_valid_internal_bundle_item_type() || - is_same_any_v); if constexpr (std::is_same_v) { fn(std::forward(value)); } @@ -266,13 +241,8 @@ template inline void to_stored_type(T &&value, Fn &&fn) fn(BundleItemValue{BundleItemInternalValue{ImplicitSharingPtr{sharing_info}}}); } else if (const bke::bNodeSocketType *socket_type = socket_type_info_by_static_type()) { - if constexpr (geo_nodes_type_stored_as_SocketValueVariant_v) { - auto value_variant = bke::SocketValueVariant::From(std::forward(value)); - fn(BundleItemValue{BundleItemSocketValue{socket_type, &value_variant}}); - } - else { - fn(BundleItemValue{BundleItemSocketValue{socket_type, &value}}); - } + auto value_variant = bke::SocketValueVariant::From(std::forward(value)); + fn(BundleItemValue{BundleItemSocketValue{socket_type, &value_variant}}); } else { /* All allowed types should be handled above already. */ diff --git a/source/blender/nodes/NOD_geometry_nodes_values.hh b/source/blender/nodes/NOD_geometry_nodes_values.hh index 41d7c3d2d76..85f7de1fbab 100644 --- a/source/blender/nodes/NOD_geometry_nodes_values.hh +++ b/source/blender/nodes/NOD_geometry_nodes_values.hh @@ -6,6 +6,7 @@ #include "BKE_geometry_set.hh" #include "BKE_node.hh" +#include "BKE_node_socket_value.hh" #include "BKE_volume_grid_fwd.hh" #include "BLI_color.hh" @@ -32,36 +33,12 @@ struct GeoNodesUserData; namespace blender::nodes { -/** True if a static type can also exist as field in Geometry Nodes. */ -template -static constexpr bool geo_nodes_is_field_base_type_v = is_same_any_v; - -/** True if Geometry Nodes sockets can store values of the given type and the type is stored - * embedded in a #SocketValueVariant. */ -template -static constexpr bool geo_nodes_type_stored_as_SocketValueVariant_v = - std::is_enum_v || geo_nodes_is_field_base_type_v || fn::is_field_v || - bke::is_VolumeGrid_v || - is_same_any_v; +template struct GeoNodesMultiInput { + using value_type = T; + Vector values; +}; +template constexpr bool is_GeoNodesMultiInput_v = false; +template constexpr bool is_GeoNodesMultiInput_v> = true; /** * Executes a multi-function. If all inputs are single values, the results will also be single diff --git a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc index c94a15ec100..eff2c306d94 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc @@ -140,13 +140,10 @@ static void node_geo_exec(GeoNodeExecParams params) } } - Vector values = params.extract_input>("Mesh 2"); - Vector geometry_sets; - for (SocketValueVariant &value : values) { - geometry_sets.append(value.extract()); - } + GeoNodesMultiInput geometry_sets = + params.extract_input>("Mesh 2"); - for (const GeometrySet &geometry : geometry_sets) { + for (const GeometrySet &geometry : geometry_sets.values) { if (const Mesh *mesh = geometry.get_mesh()) { meshes.append(mesh); transforms.append(float4x4::identity()); @@ -251,7 +248,7 @@ static void node_geo_exec(GeoNodeExecParams params) Vector all_geometries; all_geometries.append(set_a); - all_geometries.extend(geometry_sets); + all_geometries.extend(geometry_sets.values); const std::array types_to_join = {GeometryComponent::Type::Edit}; GeometrySet result_geometry = geometry::join_geometries( diff --git a/source/blender/nodes/geometry/nodes/node_geo_geometry_to_instance.cc b/source/blender/nodes/geometry/nodes/node_geo_geometry_to_instance.cc index c4026fbc88d..44f7092e36c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_geometry_to_instance.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_geometry_to_instance.cc @@ -18,12 +18,11 @@ static void node_declare(NodeDeclarationBuilder &b) static void node_geo_exec(GeoNodeExecParams params) { - Vector input_values = params.extract_input>( - "Geometry"); + GeoNodesMultiInput geometries = + params.extract_input>("Geometry"); std::unique_ptr instances = std::make_unique(); - for (bke::SocketValueVariant &value : input_values) { - bke::GeometrySet geometry = value.extract(); + for (GeometrySet &geometry : geometries.values) { geometry.ensure_owns_direct_data(); const int handle = instances->add_reference(std::move(geometry)); instances->add_instance(handle, float4x4::identity()); diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc index 62a66d73479..15fd6fc3c88 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc @@ -20,20 +20,16 @@ static void node_declare(NodeDeclarationBuilder &b) static void node_geo_exec(GeoNodeExecParams params) { - Vector input_values = params.extract_input>( - "Geometry"); - Vector geometry_sets; - for (SocketValueVariant &value : input_values) { - geometry_sets.append(value.extract()); - } + GeoNodesMultiInput geometries = + params.extract_input>("Geometry"); const NodeAttributeFilter &attribute_filter = params.get_attribute_filter("Geometry"); - for (GeometrySet &geometry : geometry_sets) { + for (GeometrySet &geometry : geometries.values) { GeometryComponentEditData::remember_deformed_positions_if_necessary(geometry); } - GeometrySet geometry_set_result = geometry::join_geometries(geometry_sets, attribute_filter); + GeometrySet geometry_set_result = geometry::join_geometries(geometries.values, attribute_filter); params.set_output("Geometry", std::move(geometry_set_result)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_sdf_grid_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_sdf_grid_boolean.cc index c18d3820448..54c2e0c6249 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sdf_grid_boolean.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sdf_grid_boolean.cc @@ -81,35 +81,23 @@ static void node_init(bNodeTree * /*tree*/, bNode *node) node->custom1 = int16_t(Operation::Difference); } -#ifdef WITH_OPENVDB -static void get_float_grids(MutableSpan values, - Vector> &grids) -{ - for (SocketValueVariant &input : values) { - if (auto grid = input.extract>()) { - grids.append(std::move(grid)); - } - } -} -#endif - static void node_geo_exec(GeoNodeExecParams params) { #ifdef WITH_OPENVDB const Operation operation = Operation(params.node().custom1); - Vector inputs = params.extract_input>("Grid 2"); + auto grids = params.extract_input>>("Grid 2"); Vector> operands; switch (operation) { case Operation::Intersect: case Operation::Union: - get_float_grids(inputs, operands); + operands.extend(grids.values); break; case Operation::Difference: if (auto grid = params.extract_input>("Grid 1")) { operands.append(std::move(grid)); } - get_float_grids(inputs, operands); + operands.extend(grids.values); break; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_string_join.cc b/source/blender/nodes/geometry/nodes/node_geo_string_join.cc index 3c66c6c2426..8df6cb7da0a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_string_join.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_string_join.cc @@ -17,13 +17,13 @@ static void node_declare(NodeDeclarationBuilder &b) static void node_geo_exec(GeoNodeExecParams params) { - Vector strings = params.extract_input>("Strings"); + auto strings = params.extract_input>("Strings"); const std::string delim = params.extract_input("Delimiter"); std::string output; - for (const int i : strings.index_range()) { - output += strings[i].extract(); - if (i < (strings.size() - 1)) { + for (const int i : strings.values.index_range()) { + output += strings.values[i]; + if (i < (strings.values.size() - 1)) { output += delim; } } diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc index 40966680cdf..4f25ffd77bd 100644 --- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc +++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc @@ -87,15 +87,6 @@ static const CPPType *get_socket_cpp_type(const bNodeSocket &socket) return get_socket_cpp_type(*socket.typeinfo); } -static const CPPType *get_vector_type(const CPPType &type) -{ - const VectorCPPType *vector_type = VectorCPPType::get_from_value(type); - if (vector_type == nullptr) { - return nullptr; - } - return &vector_type->self; -} - /** * Checks which sockets of the node are available and creates corresponding inputs/outputs on the * lazy-function. @@ -116,7 +107,7 @@ static void lazy_function_interface_from_node(const bNode &node, continue; } if (socket->is_multi_input() && !is_muted) { - type = get_vector_type(*type); + type = &CPPType::get>(); } r_lf_index_by_bsocket[socket->index_in_tree()] = r_inputs.append_and_get_index_as( socket->name, *type, input_usage); @@ -326,17 +317,12 @@ class LazyFunctionForGeometryNode : public LazyFunction { * multi-inputs are not supported in lazy-function graphs. */ class LazyFunctionForMultiInput : public LazyFunction { - private: - const CPPType *base_type_; - public: Vector links; LazyFunctionForMultiInput(const bNodeSocket &socket) { debug_name_ = "Multi Input"; - base_type_ = get_socket_cpp_type(socket); - BLI_assert(base_type_ != nullptr); BLI_assert(socket.is_multi_input()); for (const bNodeLink *link : socket.directly_linked_links()) { if (link->is_muted() || !link->fromsock->is_available() || @@ -344,21 +330,18 @@ class LazyFunctionForMultiInput : public LazyFunction { { continue; } - inputs_.append({"Input", *base_type_}); + inputs_.append({"Input", CPPType::get()}); this->links.append(link); } - const CPPType *vector_type = get_vector_type(*base_type_); - BLI_assert(vector_type != nullptr); - outputs_.append({"Output", *vector_type}); + outputs_.append({"Output", CPPType::get>()}); } void execute_impl(lf::Params ¶ms, const lf::Context & /*context*/) const override { - BLI_assert(base_type_ == &CPPType::get()); void *output_ptr = params.get_output_data_ptr(0); - auto &values = *new (output_ptr) Vector(); + auto &values = *new (output_ptr) GeoNodesMultiInput(); for (const int i : inputs_.index_range()) { - values.append(params.extract_input(i)); + values.values.append(params.extract_input(i)); } params.output_set(0); } diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc index ea809d72bfe..496306d72ea 100644 --- a/source/blender/nodes/intern/node_geometry_exec.cc +++ b/source/blender/nodes/intern/node_geometry_exec.cc @@ -172,8 +172,7 @@ void GeoNodeExecParams::set_default_remaining_outputs() set_default_remaining_node_outputs(params_, node_); } -void GeoNodeExecParams::check_input_access(StringRef identifier, - const CPPType *requested_type) const +void GeoNodeExecParams::check_input_access(StringRef identifier) const { const bNodeSocket *found_socket = nullptr; for (const bNodeSocket *socket : node_.input_sockets()) { @@ -199,17 +198,9 @@ void GeoNodeExecParams::check_input_access(StringRef identifier, << "' is disabled.\n"; BLI_assert_unreachable(); } - else if (requested_type != nullptr && (found_socket->flag & SOCK_MULTI_INPUT) == 0) { - const CPPType &expected_type = *found_socket->typeinfo->geometry_nodes_cpp_type; - if (*requested_type != expected_type) { - std::cout << "The requested type '" << requested_type->name() << "' is incorrect. Expected '" - << expected_type.name() << "'.\n"; - BLI_assert_unreachable(); - } - } } -void GeoNodeExecParams::check_output_access(StringRef identifier, const CPPType &value_type) const +void GeoNodeExecParams::check_output_access(StringRef identifier) const { const bNodeSocket *found_socket = nullptr; for (const bNodeSocket *socket : node_.output_sockets()) { @@ -239,14 +230,6 @@ void GeoNodeExecParams::check_output_access(StringRef identifier, const CPPType std::cout << "The identifier '" << identifier << "' has been set already.\n"; BLI_assert_unreachable(); } - else { - const CPPType &expected_type = *found_socket->typeinfo->geometry_nodes_cpp_type; - if (value_type != expected_type) { - std::cout << "The value type '" << value_type.name() << "' is incorrect. Expected '" - << expected_type.name() << "'.\n"; - BLI_assert_unreachable(); - } - } } AttributeFilter::Result NodeAttributeFilter::filter(const StringRef attribute_name) const