Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc
| Show All 28 Lines | |||||
| static void node_declare(NodeDeclarationBuilder &b) | static void node_declare(NodeDeclarationBuilder &b) | ||||
| { | { | ||||
| b.add_input<decl::Geometry>(N_("Source")) | b.add_input<decl::Geometry>(N_("Source")) | ||||
| .supported_type({GEO_COMPONENT_TYPE_MESH, | .supported_type({GEO_COMPONENT_TYPE_MESH, | ||||
| GEO_COMPONENT_TYPE_POINT_CLOUD, | GEO_COMPONENT_TYPE_POINT_CLOUD, | ||||
| GEO_COMPONENT_TYPE_CURVE, | GEO_COMPONENT_TYPE_CURVE, | ||||
| GEO_COMPONENT_TYPE_INSTANCES}); | GEO_COMPONENT_TYPE_INSTANCES}); | ||||
| b.add_input<decl::Vector>(N_("Attribute")).hide_value().supports_field(); | b.add_input<decl::Vector>(N_("Attribute"), "Attribute_Vector").hide_value().supports_field(); | ||||
| b.add_input<decl::Float>(N_("Attribute"), "Attribute_001").hide_value().supports_field(); | b.add_input<decl::Float>(N_("Attribute"), "Attribute_Float").hide_value().supports_field(); | ||||
| b.add_input<decl::Color>(N_("Attribute"), "Attribute_002").hide_value().supports_field(); | b.add_input<decl::Color>(N_("Attribute"), "Attribute_Color").hide_value().supports_field(); | ||||
| b.add_input<decl::Bool>(N_("Attribute"), "Attribute_003").hide_value().supports_field(); | b.add_input<decl::Bool>(N_("Attribute"), "Attribute_Bool").hide_value().supports_field(); | ||||
| b.add_input<decl::Int>(N_("Attribute"), "Attribute_004").hide_value().supports_field(); | b.add_input<decl::Int>(N_("Attribute"), "Attribute_Int").hide_value().supports_field(); | ||||
| b.add_input<decl::Vector>(N_("Source Position")) | b.add_input<decl::Vector>(N_("Source Position")) | ||||
| .implicit_field() | .implicit_field() | ||||
| .make_available([](bNode &node) { | .make_available([](bNode &node) { | ||||
| node_storage(node).mode = GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED; | node_storage(node).mode = GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED; | ||||
| }); | }); | ||||
| b.add_input<decl::Int>(N_("Index")).implicit_field().make_available([](bNode &node) { | b.add_input<decl::Int>(N_("Index")).implicit_field().make_available([](bNode &node) { | ||||
| node_storage(node).mode = GEO_NODE_ATTRIBUTE_TRANSFER_INDEX; | node_storage(node).mode = GEO_NODE_ATTRIBUTE_TRANSFER_INDEX; | ||||
| }); | }); | ||||
| b.add_output<decl::Vector>(N_("Attribute")).dependent_field({6, 7}); | b.add_output<decl::Vector>(N_("Attribute"), "Attribute_Vector").dependent_field({6, 7}); | ||||
| b.add_output<decl::Float>(N_("Attribute"), "Attribute_001").dependent_field({6, 7}); | b.add_output<decl::Float>(N_("Attribute"), "Attribute_Float").dependent_field({6, 7}); | ||||
| b.add_output<decl::Color>(N_("Attribute"), "Attribute_002").dependent_field({6, 7}); | b.add_output<decl::Color>(N_("Attribute"), "Attribute_Color").dependent_field({6, 7}); | ||||
| b.add_output<decl::Bool>(N_("Attribute"), "Attribute_003").dependent_field({6, 7}); | b.add_output<decl::Bool>(N_("Attribute"), "Attribute_Bool").dependent_field({6, 7}); | ||||
| b.add_output<decl::Int>(N_("Attribute"), "Attribute_004").dependent_field({6, 7}); | b.add_output<decl::Int>(N_("Attribute"), "Attribute_Int").dependent_field({6, 7}); | ||||
| } | } | ||||
| static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) | static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) | ||||
| { | { | ||||
| const bNode &node = *static_cast<const bNode *>(ptr->data); | const bNode &node = *static_cast<const bNode *>(ptr->data); | ||||
| const NodeGeometryTransferAttribute &storage = node_storage(node); | const NodeGeometryTransferAttribute &storage = node_storage(node); | ||||
| const GeometryNodeAttributeTransferMode mapping = (GeometryNodeAttributeTransferMode) | const GeometryNodeAttributeTransferMode mapping = (GeometryNodeAttributeTransferMode) | ||||
| storage.mode; | storage.mode; | ||||
| ▲ Show 20 Lines • Show All 614 Lines • ▼ Show 20 Lines | void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override | ||||
| attribute_math::convert_to_static_type(type, [&](auto dummy) { | attribute_math::convert_to_static_type(type, [&](auto dummy) { | ||||
| using T = decltype(dummy); | using T = decltype(dummy); | ||||
| copy_with_indices_clamped(src_data_->typed<T>(), mask, indices, dst.typed<T>()); | copy_with_indices_clamped(src_data_->typed<T>(), mask, indices, dst.typed<T>()); | ||||
| }); | }); | ||||
| } | } | ||||
| }; | }; | ||||
| static GField get_input_attribute_field(GeoNodeExecParams ¶ms, const eCustomDataType data_type) | |||||
| { | |||||
| switch (data_type) { | |||||
| case CD_PROP_FLOAT: | |||||
| return params.extract_input<Field<float>>("Attribute_001"); | |||||
| case CD_PROP_FLOAT3: | |||||
| return params.extract_input<Field<float3>>("Attribute"); | |||||
| case CD_PROP_COLOR: | |||||
| return params.extract_input<Field<ColorGeometry4f>>("Attribute_002"); | |||||
| case CD_PROP_BOOL: | |||||
| return params.extract_input<Field<bool>>("Attribute_003"); | |||||
| case CD_PROP_INT32: | |||||
| return params.extract_input<Field<int>>("Attribute_004"); | |||||
| default: | |||||
| BLI_assert_unreachable(); | |||||
| } | |||||
| return {}; | |||||
| } | |||||
| static void output_attribute_field(GeoNodeExecParams ¶ms, GField field) | |||||
| { | |||||
| switch (bke::cpp_type_to_custom_data_type(field.cpp_type())) { | |||||
| case CD_PROP_FLOAT: { | |||||
| params.set_output("Attribute_001", Field<float>(field)); | |||||
| break; | |||||
| } | |||||
| case CD_PROP_FLOAT3: { | |||||
| params.set_output("Attribute", Field<float3>(field)); | |||||
| break; | |||||
| } | |||||
| case CD_PROP_COLOR: { | |||||
| params.set_output("Attribute_002", Field<ColorGeometry4f>(field)); | |||||
| break; | |||||
| } | |||||
| case CD_PROP_BOOL: { | |||||
| params.set_output("Attribute_003", Field<bool>(field)); | |||||
| break; | |||||
| } | |||||
| case CD_PROP_INT32: { | |||||
| params.set_output("Attribute_004", Field<int>(field)); | |||||
| break; | |||||
| } | |||||
| default: | |||||
| break; | |||||
| } | |||||
| } | |||||
| static void node_geo_exec(GeoNodeExecParams params) | static void node_geo_exec(GeoNodeExecParams params) | ||||
| { | { | ||||
| GeometrySet geometry = params.extract_input<GeometrySet>("Source"); | GeometrySet geometry = params.extract_input<GeometrySet>("Source"); | ||||
| const NodeGeometryTransferAttribute &storage = node_storage(params.node()); | const NodeGeometryTransferAttribute &storage = node_storage(params.node()); | ||||
| const GeometryNodeAttributeTransferMode mapping = (GeometryNodeAttributeTransferMode) | const GeometryNodeAttributeTransferMode mapping = (GeometryNodeAttributeTransferMode) | ||||
| storage.mode; | storage.mode; | ||||
| const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); | const eCustomDataType data_type = static_cast<eCustomDataType>(storage.data_type); | ||||
| const eAttrDomain domain = static_cast<eAttrDomain>(storage.domain); | const eAttrDomain domain = static_cast<eAttrDomain>(storage.domain); | ||||
| GField field = get_input_attribute_field(params, data_type); | std::string socket_name = "Attribute_" + attribute_math::default_name(data_type); | ||||
| auto return_default = [&]() { | GField field; | ||||
| attribute_math::convert_to_static_type(data_type, [&](auto dummy) { | attribute_math::convert_to_static_type(data_type, [&](auto dummy) { | ||||
| using T = decltype(dummy); | using T = decltype(dummy); | ||||
| output_attribute_field(params, fn::make_constant_field<T>(T())); | field = params.extract_input<Field<T>>(socket_name); | ||||
| }); | }); | ||||
| }; | |||||
| GField output_field; | GField output_field; | ||||
| switch (mapping) { | switch (mapping) { | ||||
| case GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED: { | case GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED: { | ||||
| const Mesh *mesh = geometry.get_mesh_for_read(); | const Mesh *mesh = geometry.get_mesh_for_read(); | ||||
| if (mesh == nullptr) { | if (mesh == nullptr) { | ||||
| if (!geometry.is_empty()) { | if (!geometry.is_empty()) { | ||||
| params.error_message_add(NodeWarningType::Error, | params.error_message_add(NodeWarningType::Error, | ||||
| TIP_("The source geometry must contain a mesh")); | TIP_("The source geometry must contain a mesh")); | ||||
| } | } | ||||
| return return_default(); | params.set_default_remaining_outputs(); | ||||
| return; | |||||
| } | } | ||||
| if (mesh->totpoly == 0) { | if (mesh->totpoly == 0) { | ||||
| /* Don't add a warning for empty meshes. */ | /* Don't add a warning for empty meshes. */ | ||||
| if (mesh->totvert != 0) { | if (mesh->totvert != 0) { | ||||
| params.error_message_add(NodeWarningType::Error, | params.error_message_add(NodeWarningType::Error, | ||||
| TIP_("The source mesh must have faces")); | TIP_("The source mesh must have faces")); | ||||
| } | } | ||||
| return return_default(); | params.set_default_remaining_outputs(); | ||||
| return; | |||||
| } | } | ||||
| auto fn = std::make_unique<NearestInterpolatedTransferFunction>(std::move(geometry), | auto fn = std::make_unique<NearestInterpolatedTransferFunction>(std::move(geometry), | ||||
| std::move(field)); | std::move(field)); | ||||
| auto op = std::make_shared<FieldOperation>( | auto op = std::make_shared<FieldOperation>( | ||||
| FieldOperation(std::move(fn), {params.extract_input<Field<float3>>("Source Position")})); | FieldOperation(std::move(fn), {params.extract_input<Field<float3>>("Source Position")})); | ||||
| output_field = GField(std::move(op)); | output_field = GField(std::move(op)); | ||||
| break; | break; | ||||
| } | } | ||||
| case GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST: { | case GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST: { | ||||
| if (geometry.has_curves() && !geometry.has_mesh() && !geometry.has_pointcloud()) { | if (geometry.has_curves() && !geometry.has_mesh() && !geometry.has_pointcloud()) { | ||||
| params.error_message_add(NodeWarningType::Error, | params.error_message_add(NodeWarningType::Error, | ||||
| TIP_("The source geometry must contain a mesh or a point cloud")); | TIP_("The source geometry must contain a mesh or a point cloud")); | ||||
| return return_default(); | params.set_default_remaining_outputs(); | ||||
| return; | |||||
| } | } | ||||
| auto fn = std::make_unique<NearestTransferFunction>( | auto fn = std::make_unique<NearestTransferFunction>( | ||||
| std::move(geometry), std::move(field), domain); | std::move(geometry), std::move(field), domain); | ||||
| auto op = std::make_shared<FieldOperation>( | auto op = std::make_shared<FieldOperation>( | ||||
| FieldOperation(std::move(fn), {params.extract_input<Field<float3>>("Source Position")})); | FieldOperation(std::move(fn), {params.extract_input<Field<float3>>("Source Position")})); | ||||
| output_field = GField(std::move(op)); | output_field = GField(std::move(op)); | ||||
| break; | break; | ||||
| } | } | ||||
| case GEO_NODE_ATTRIBUTE_TRANSFER_INDEX: { | case GEO_NODE_ATTRIBUTE_TRANSFER_INDEX: { | ||||
| Field<int> indices = params.extract_input<Field<int>>("Index"); | Field<int> indices = params.extract_input<Field<int>>("Index"); | ||||
| auto fn = std::make_unique<IndexTransferFunction>( | auto fn = std::make_unique<IndexTransferFunction>( | ||||
| std::move(geometry), std::move(field), domain); | std::move(geometry), std::move(field), domain); | ||||
| auto op = std::make_shared<FieldOperation>( | auto op = std::make_shared<FieldOperation>( | ||||
| FieldOperation(std::move(fn), {std::move(indices)})); | FieldOperation(std::move(fn), {std::move(indices)})); | ||||
| output_field = GField(std::move(op)); | output_field = GField(std::move(op)); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| output_attribute_field(params, std::move(output_field)); | attribute_math::convert_to_static_type(data_type, [&](auto dummy) { | ||||
| using T = decltype(dummy); | |||||
| params.set_output(socket_name, Field<T>(output_field)); | |||||
| }); | |||||
| } | } | ||||
| } // namespace blender::nodes::node_geo_transfer_attribute_cc | } // namespace blender::nodes::node_geo_transfer_attribute_cc | ||||
| void register_node_type_geo_transfer_attribute() | void register_node_type_geo_transfer_attribute() | ||||
| { | { | ||||
| namespace file_ns = blender::nodes::node_geo_transfer_attribute_cc; | namespace file_ns = blender::nodes::node_geo_transfer_attribute_cc; | ||||
| Show All 16 Lines | |||||