diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index fe3c97827f2..361b239cb11 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -210,12 +210,6 @@ struct GeometrySet { * Remove all geometry components with types that are not in the provided list. */ void keep_only(Span component_types); - /** - * Keeps the provided geometry types, but also instances and edit data. - * Instances must not be removed while using #modify_geometry_sets. - */ - void keep_only_during_modify(Span component_types); - void remove_geometry_during_modify(); void add(const GeometryComponent &component); @@ -272,14 +266,6 @@ struct GeometrySet { Vector gather_component_types(bool include_instances, bool ignore_empty) const; - using ForeachSubGeometryCallback = FunctionRef; - - /** - * Modify every (recursive) instance separately. This is often more efficient than realizing all - * instances just to change the same thing on all of them. - */ - void modify_geometry_sets(ForeachSubGeometryCallback callback); - /* Utility methods for creation. */ /** * Create a new geometry set that only contains the given mesh. diff --git a/source/blender/blenkernel/BKE_instances.hh b/source/blender/blenkernel/BKE_instances.hh index 9805f076b37..9cb441e7f93 100644 --- a/source/blender/blenkernel/BKE_instances.hh +++ b/source/blender/blenkernel/BKE_instances.hh @@ -168,6 +168,8 @@ class Instances { void add_instance(int instance_handle, const float4x4 &transform); Span references() const; + MutableSpan references_for_write(); + void remove_unused_references(); /** diff --git a/source/blender/blenkernel/intern/bake_items.cc b/source/blender/blenkernel/intern/bake_items.cc index 77c4d479f09..0829153cfff 100644 --- a/source/blender/blenkernel/intern/bake_items.cc +++ b/source/blender/blenkernel/intern/bake_items.cc @@ -53,52 +53,60 @@ static std::unique_ptr materials_to_weak_references( return materials_list; } +static void prepare_geometry_for_bake_recursive(GeometrySet &geometry, + BakeDataBlockMap *data_block_map) +{ + if (Mesh *mesh = geometry.get_mesh_for_write()) { + mesh->attributes_for_write().remove_anonymous(); + mesh->runtime->bake_materials = materials_to_weak_references( + &mesh->mat, &mesh->totcol, data_block_map); + } + if (Curves *curves = geometry.get_curves_for_write()) { + curves->geometry.wrap().attributes_for_write().remove_anonymous(); + curves->geometry.runtime->bake_materials = materials_to_weak_references( + &curves->mat, &curves->totcol, data_block_map); + } + if (GreasePencil *grease_pencil = geometry.get_grease_pencil_for_write()) { + for (GreasePencilDrawingBase *base : grease_pencil->drawings()) { + if (base->type != GP_DRAWING) { + continue; + } + greasepencil::Drawing &drawing = reinterpret_cast(base)->wrap(); + drawing.strokes_for_write().attributes_for_write().remove_anonymous(); + } + grease_pencil->attributes_for_write().remove_anonymous(); + grease_pencil->runtime->bake_materials = materials_to_weak_references( + &grease_pencil->material_array, &grease_pencil->material_array_num, data_block_map); + } + if (PointCloud *pointcloud = geometry.get_pointcloud_for_write()) { + pointcloud->attributes_for_write().remove_anonymous(); + pointcloud->runtime->bake_materials = materials_to_weak_references( + &pointcloud->mat, &pointcloud->totcol, data_block_map); + } + if (Volume *volume = geometry.get_volume_for_write()) { + volume->runtime->bake_materials = materials_to_weak_references( + &volume->mat, &volume->totcol, data_block_map); + } + if (bke::Instances *instances = geometry.get_instances_for_write()) { + instances->attributes_for_write().remove_anonymous(); + instances->ensure_geometry_instances(); + for (bke::InstanceReference &reference : instances->references_for_write()) { + if (reference.type() == bke::InstanceReference::Type::GeometrySet) { + prepare_geometry_for_bake_recursive(reference.geometry_set(), data_block_map); + } + else { + /* Can only bake geometry instances currently. */ + reference = bke::InstanceReference(); + } + } + } +} + void GeometryBakeItem::prepare_geometry_for_bake(GeometrySet &main_geometry, BakeDataBlockMap *data_block_map) { main_geometry.ensure_owns_all_data(); - main_geometry.modify_geometry_sets([&](GeometrySet &geometry) { - if (Mesh *mesh = geometry.get_mesh_for_write()) { - mesh->attributes_for_write().remove_anonymous(); - mesh->runtime->bake_materials = materials_to_weak_references( - &mesh->mat, &mesh->totcol, data_block_map); - } - if (Curves *curves = geometry.get_curves_for_write()) { - curves->geometry.wrap().attributes_for_write().remove_anonymous(); - curves->geometry.runtime->bake_materials = materials_to_weak_references( - &curves->mat, &curves->totcol, data_block_map); - } - if (GreasePencil *grease_pencil = geometry.get_grease_pencil_for_write()) { - for (GreasePencilDrawingBase *base : grease_pencil->drawings()) { - if (base->type != GP_DRAWING) { - continue; - } - greasepencil::Drawing &drawing = reinterpret_cast(base)->wrap(); - drawing.strokes_for_write().attributes_for_write().remove_anonymous(); - } - grease_pencil->attributes_for_write().remove_anonymous(); - grease_pencil->runtime->bake_materials = materials_to_weak_references( - &grease_pencil->material_array, &grease_pencil->material_array_num, data_block_map); - } - if (PointCloud *pointcloud = geometry.get_pointcloud_for_write()) { - pointcloud->attributes_for_write().remove_anonymous(); - pointcloud->runtime->bake_materials = materials_to_weak_references( - &pointcloud->mat, &pointcloud->totcol, data_block_map); - } - if (Volume *volume = geometry.get_volume_for_write()) { - volume->runtime->bake_materials = materials_to_weak_references( - &volume->mat, &volume->totcol, data_block_map); - } - if (bke::Instances *instances = geometry.get_instances_for_write()) { - instances->attributes_for_write().remove_anonymous(); - } - geometry.keep_only_during_modify({GeometryComponent::Type::Mesh, - GeometryComponent::Type::Curve, - GeometryComponent::Type::GreasePencil, - GeometryComponent::Type::PointCloud, - GeometryComponent::Type::Volume, - GeometryComponent::Type::Instance}); - }); + prepare_geometry_for_bake_recursive(main_geometry, data_block_map); } static void restore_materials(Material ***materials, @@ -125,39 +133,47 @@ static void restore_materials(Material ***materials, } } +static void restore_data_blocks_recursive(GeometrySet &geometry, BakeDataBlockMap *data_block_map) +{ + if (Mesh *mesh = geometry.get_mesh_for_write()) { + restore_materials( + &mesh->mat, &mesh->totcol, std::move(mesh->runtime->bake_materials), data_block_map); + } + if (Curves *curves = geometry.get_curves_for_write()) { + restore_materials(&curves->mat, + &curves->totcol, + std::move(curves->geometry.runtime->bake_materials), + data_block_map); + } + if (GreasePencil *grease_pencil = geometry.get_grease_pencil_for_write()) { + restore_materials(&grease_pencil->material_array, + &grease_pencil->material_array_num, + std::move(grease_pencil->runtime->bake_materials), + data_block_map); + } + if (PointCloud *pointcloud = geometry.get_pointcloud_for_write()) { + restore_materials(&pointcloud->mat, + &pointcloud->totcol, + std::move(pointcloud->runtime->bake_materials), + data_block_map); + } + if (Volume *volume = geometry.get_volume_for_write()) { + restore_materials( + &volume->mat, &volume->totcol, std::move(volume->runtime->bake_materials), data_block_map); + } + if (bke::Instances *instances = geometry.get_instances_for_write()) { + for (bke::InstanceReference &reference : instances->references_for_write()) { + if (reference.type() == bke::InstanceReference::Type::GeometrySet) { + restore_data_blocks_recursive(reference.geometry_set(), data_block_map); + } + } + } +} + void GeometryBakeItem::try_restore_data_blocks(GeometrySet &main_geometry, BakeDataBlockMap *data_block_map) { - main_geometry.modify_geometry_sets([&](GeometrySet &geometry) { - if (Mesh *mesh = geometry.get_mesh_for_write()) { - restore_materials( - &mesh->mat, &mesh->totcol, std::move(mesh->runtime->bake_materials), data_block_map); - } - if (Curves *curves = geometry.get_curves_for_write()) { - restore_materials(&curves->mat, - &curves->totcol, - std::move(curves->geometry.runtime->bake_materials), - data_block_map); - } - if (GreasePencil *grease_pencil = geometry.get_grease_pencil_for_write()) { - restore_materials(&grease_pencil->material_array, - &grease_pencil->material_array_num, - std::move(grease_pencil->runtime->bake_materials), - data_block_map); - } - if (PointCloud *pointcloud = geometry.get_pointcloud_for_write()) { - restore_materials(&pointcloud->mat, - &pointcloud->totcol, - std::move(pointcloud->runtime->bake_materials), - data_block_map); - } - if (Volume *volume = geometry.get_volume_for_write()) { - restore_materials(&volume->mat, - &volume->totcol, - std::move(volume->runtime->bake_materials), - data_block_map); - } - }); + restore_data_blocks_recursive(main_geometry, data_block_map); } #ifdef WITH_OPENVDB diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc index 22bd4bdbd8d..d397b64a254 100644 --- a/source/blender/blenkernel/intern/geometry_set.cc +++ b/source/blender/blenkernel/intern/geometry_set.cc @@ -164,19 +164,6 @@ void GeometrySet::keep_only(const Span component_types) } } -void GeometrySet::keep_only_during_modify(const Span component_types) -{ - Vector extended_types = component_types; - extended_types.append_non_duplicates(GeometryComponent::Type::Instance); - extended_types.append_non_duplicates(GeometryComponent::Type::Edit); - this->keep_only(extended_types); -} - -void GeometrySet::remove_geometry_during_modify() -{ - this->keep_only_during_modify({}); -} - void GeometrySet::add(const GeometryComponent &component) { BLI_assert(!components_[size_t(component.type())]); @@ -796,39 +783,6 @@ Vector GeometrySet::gather_component_types(const bool i return types; } -static void gather_mutable_geometry_sets(GeometrySet &geometry_set, - Vector &r_geometry_sets) -{ - r_geometry_sets.append(&geometry_set); - if (!geometry_set.has_instances()) { - return; - } - /* In the future this can be improved by deduplicating instance references across different - * instances. */ - Instances &instances = *geometry_set.get_instances_for_write(); - instances.ensure_geometry_instances(); - for (const int handle : instances.references().index_range()) { - if (instances.references()[handle].type() == InstanceReference::Type::GeometrySet) { - GeometrySet &instance_geometry = instances.geometry_set_from_reference(handle); - gather_mutable_geometry_sets(instance_geometry, r_geometry_sets); - } - } -} - -void GeometrySet::modify_geometry_sets(ForeachSubGeometryCallback callback) -{ - Vector geometry_sets; - gather_mutable_geometry_sets(*this, geometry_sets); - if (geometry_sets.size() == 1) { - /* Avoid possible overhead and a large call stack when multithreading is pointless. */ - callback(*geometry_sets.first()); - } - else { - threading::parallel_for_each(geometry_sets, - [&](GeometrySet *geometry_set) { callback(*geometry_set); }); - } -} - bool object_has_geometry_set_instances(const Object &object) { const GeometrySet *geometry_set = object.runtime->geometry_set_eval; diff --git a/source/blender/blenkernel/intern/instances.cc b/source/blender/blenkernel/intern/instances.cc index f13b6594f77..5d9f1fb7fc7 100644 --- a/source/blender/blenkernel/intern/instances.cc +++ b/source/blender/blenkernel/intern/instances.cc @@ -275,6 +275,11 @@ Span Instances::references() const return references_; } +MutableSpan Instances::references_for_write() +{ + return references_; +} + void Instances::remove(const IndexMask &mask, const AttributeFilter &attribute_filter) { const std::optional masked_range = mask.to_range(); diff --git a/source/blender/geometry/CMakeLists.txt b/source/blender/geometry/CMakeLists.txt index e0fea3982b7..096d61fcd20 100644 --- a/source/blender/geometry/CMakeLists.txt +++ b/source/blender/geometry/CMakeLists.txt @@ -20,6 +20,7 @@ set(SRC intern/fillet_curves.cc intern/fit_curves.cc intern/interpolate_curves.cc + intern/foreach_geometry.cc intern/join_geometries.cc intern/merge_curves.cc intern/merge_layers.cc @@ -63,6 +64,7 @@ set(SRC GEO_extract_elements.hh GEO_fillet_curves.hh GEO_fit_curves.hh + GEO_foreach_geometry.hh GEO_interpolate_curves.hh GEO_join_geometries.hh GEO_merge_curves.hh diff --git a/source/blender/geometry/GEO_foreach_geometry.hh b/source/blender/geometry/GEO_foreach_geometry.hh new file mode 100644 index 00000000000..8bf8858ff05 --- /dev/null +++ b/source/blender/geometry/GEO_foreach_geometry.hh @@ -0,0 +1,19 @@ +/* SPDX-FileCopyrightText: 2025 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#include "BKE_geometry_set.hh" + +namespace blender::geometry { + +/** + * Modify every real geometry separately, including those from instances. The input to the + * callback never contains instances. Newly generated instances will be merged with the + * previously existing ones. + */ +void foreach_real_geometry(bke::GeometrySet &geometry, + FunctionRef fn); + +} // namespace blender::geometry diff --git a/source/blender/geometry/GEO_join_geometries.hh b/source/blender/geometry/GEO_join_geometries.hh index f278f3c1168..caed60f6599 100644 --- a/source/blender/geometry/GEO_join_geometries.hh +++ b/source/blender/geometry/GEO_join_geometries.hh @@ -8,10 +8,18 @@ namespace blender::geometry { +/** + * \param allow_merging_instance_references: If true, instance references from multiple instances + * components may be merged when they are the same. This is typically good because it reduces the + * amount of processing for later nodes. However, this may be undesirable in some cases if the + * instance references are modified afterwards and the calling code assumes that the instances + * references are just concatenated. + */ bke::GeometrySet join_geometries(Span geometries, const bke::AttributeFilter &attribute_filter, const std::optional> - &component_types_to_join = std::nullopt); + &component_types_to_join = std::nullopt, + bool allow_merging_instance_references = true); void join_attributes(const Span src_components, bke::GeometryComponent &r_result, diff --git a/source/blender/geometry/intern/foreach_geometry.cc b/source/blender/geometry/intern/foreach_geometry.cc new file mode 100644 index 00000000000..01c6dab6b72 --- /dev/null +++ b/source/blender/geometry/intern/foreach_geometry.cc @@ -0,0 +1,105 @@ +/* SPDX-FileCopyrightText: 2025 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BKE_geometry_set.hh" +#include "BKE_instances.hh" + +#include "GEO_foreach_geometry.hh" +#include "GEO_join_geometries.hh" + +namespace blender::geometry { + +static void extract_real_geometries_recursive( + bke::GeometrySet &geometry, + Vector &path, + Map>> &r_real_geometries) +{ + bke::GeometrySet real_geometry = geometry; + real_geometry.remove(bke::GeometryComponent::Type::Instance); + geometry.keep_only({bke::GeometryComponent::Type::Instance}); + + r_real_geometries.lookup_or_add_default(std::move(real_geometry)).append(path); + + bke::Instances *instances = geometry.get_instances_for_write(); + if (!instances) { + return; + } + instances->ensure_geometry_instances(); + MutableSpan references = instances->references_for_write(); + for (const int i : references.index_range()) { + bke::InstanceReference &reference = references[i]; + if (reference.type() == bke::InstanceReference::Type::GeometrySet) { + bke::GeometrySet &sub_geometry = reference.geometry_set(); + path.append(i); + extract_real_geometries_recursive(sub_geometry, path, r_real_geometries); + path.pop_last(); + } + } +} + +static void reinsert_modified_geometry_recursive(bke::GeometrySet &geometry, + const bke::GeometrySet &geometry_to_insert, + const Span path) +{ + if (path.is_empty()) { + /* Instance references must not be merged here as that could invalidate the paths. */ + const bool allow_merging_instance_references = false; + /* Important to pass the old geometry first, so that the instance reference paths stay + * valid. */ + geometry = join_geometries( + {geometry, geometry_to_insert}, {}, {}, allow_merging_instance_references); + return; + } + bke::Instances *instances = geometry.get_instances_for_write(); + BLI_assert(instances); + const int reference_i = path.first(); + const MutableSpan references = instances->references_for_write(); + BLI_assert(reference_i < references.size()); + bke::InstanceReference &reference = references[reference_i]; + BLI_assert(reference.type() == bke::InstanceReference::Type::GeometrySet); + bke::GeometrySet &sub_geometry = reference.geometry_set(); + reinsert_modified_geometry_recursive(sub_geometry, geometry_to_insert, path.drop_front(1)); +} + +struct GeometryWithPaths { + bke::GeometrySet geometry; + Vector> paths; +}; + +void foreach_real_geometry(bke::GeometrySet &geometry, + FunctionRef fn) +{ + /* Afterwards the geometry does not have realized geometry anymore. It has been extracted and + * will be reinserted afterwards. */ + Map>> real_geometries; + { + Vector path; + extract_real_geometries_recursive(geometry, path, real_geometries); + } + /* Take the geometries out of the map so that they can be edited in-place. As keys in the #Map + * the geometries are const and thus can't be modified. */ + Vector geometries_with_paths; + for (auto &&item : real_geometries.items()) { + geometries_with_paths.append({item.key, std::move(item.value)}); + } + /* Clear to avoid extra references to the geometries which prohibit editing them in-place. */ + real_geometries.clear(); + + /* Actually modify the geometries in parallel. */ + threading::parallel_for(geometries_with_paths.index_range(), 1, [&](const IndexRange range) { + for (const int i : range) { + bke::GeometrySet &geometry_to_modify = geometries_with_paths[i].geometry; + fn(geometry_to_modify); + } + }); + + /* Reinsert modified geometries. */ + for (GeometryWithPaths &geometry_with_paths : geometries_with_paths) { + for (const Span path : geometry_with_paths.paths) { + reinsert_modified_geometry_recursive(geometry, geometry_with_paths.geometry, path); + } + } +} + +} // namespace blender::geometry diff --git a/source/blender/geometry/intern/join_geometries.cc b/source/blender/geometry/intern/join_geometries.cc index 4a9dd5d749b..ebdf1a9de8f 100644 --- a/source/blender/geometry/intern/join_geometries.cc +++ b/source/blender/geometry/intern/join_geometries.cc @@ -95,6 +95,7 @@ void join_attributes(const Span src_components, } static void join_instances(const Span src_components, + const bool allow_merging_instance_references, GeometrySet &result) { Array offsets_data(src_components.size() + 1); @@ -109,7 +110,7 @@ static void join_instances(const Span src_components, MutableSpan all_handles = dst_instances->reference_handles_for_write(); - Map, int> new_handle_by_src_reference; + Map, int> new_handle_by_src_reference_cache; for (const int i : src_components.index_range()) { const auto &src_component = static_cast(*src_components[i]); @@ -119,8 +120,13 @@ static void join_instances(const Span src_components, Array handle_map(src_references.size()); for (const int src_handle : src_references.index_range()) { const bke::InstanceReference &src_reference = src_references[src_handle]; - handle_map[src_handle] = new_handle_by_src_reference.lookup_or_add_cb( - src_reference, [&]() { return dst_instances->add_new_reference(src_reference); }); + if (allow_merging_instance_references) { + handle_map[src_handle] = new_handle_by_src_reference_cache.lookup_or_add_cb( + src_reference, [&]() { return dst_instances->add_new_reference(src_reference); }); + } + else { + handle_map[src_handle] = dst_instances->add_new_reference(src_reference); + } } const IndexRange dst_range = offsets[i]; @@ -144,6 +150,7 @@ static void join_volumes(const Span /*src_components* static void join_component_type(const bke::GeometryComponent::Type component_type, const Span src_geometry_sets, const bke::AttributeFilter &attribute_filter, + const bool allow_merging_instance_references, GeometrySet &result) { Vector components; @@ -164,7 +171,7 @@ static void join_component_type(const bke::GeometryComponent::Type component_typ switch (component_type) { case bke::GeometryComponent::Type::Instance: - join_instances(components, result); + join_instances(components, allow_merging_instance_references, result); return; case bke::GeometryComponent::Type::Volume: join_volumes(components, result); @@ -199,7 +206,8 @@ static void join_component_type(const bke::GeometryComponent::Type component_typ GeometrySet join_geometries( const Span geometries, const bke::AttributeFilter &attribute_filter, - const std::optional> &component_types_to_join) + const std::optional> &component_types_to_join, + const bool allow_merging_instance_references) { GeometrySet result; result.name = geometries.is_empty() ? "" : geometries[0].name; @@ -218,7 +226,8 @@ GeometrySet join_geometries( supported_types); for (const GeometryComponent::Type type : types_to_join) { - join_component_type(type, geometries, attribute_filter, result); + join_component_type( + type, geometries, attribute_filter, allow_merging_instance_references, result); } return result; diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 3f7ab4b461f..bae4c3bbc12 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -2426,11 +2426,17 @@ static void execute_realize_edit_data_tasks(const Span task static void remove_id_attribute_from_instances(bke::GeometrySet &geometry_set) { - geometry_set.modify_geometry_sets([&](bke::GeometrySet &sub_geometry) { - if (Instances *instances = sub_geometry.get_instances_for_write()) { - instances->attributes_for_write().remove("id"); + Instances *instances = geometry_set.get_instances_for_write(); + if (!instances) { + return; + } + instances->attributes_for_write().remove("id"); + instances->ensure_geometry_instances(); + for (bke::InstanceReference &reference : instances->references_for_write()) { + if (reference.type() == bke::InstanceReference::Type::GeometrySet) { + remove_id_attribute_from_instances(reference.geometry_set()); } - }); + } } /** Propagate instances from the old geometry set to the new geometry set if they are not diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc index 73584a41e1d..ec2d6fbe0e3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc @@ -18,6 +18,8 @@ #include "BKE_library.hh" #include "BKE_screen.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_attribute_capture_cc { @@ -196,7 +198,7 @@ static void node_geo_exec(GeoNodeExecParams params) GeometryComponent::Type::Curve, GeometryComponent::Type::GreasePencil}; - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { for (const GeometryComponent::Type type : types) { if (geometry_set.has(type)) { capture_on(geometry_set.get_component_for_write(type)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc index 74805459c9e..a6c02ff4ae9 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc @@ -2,6 +2,7 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ +#include "GEO_foreach_geometry.hh" #include "GEO_mesh_primitive_cuboid.hh" #include "GEO_transform.hh" @@ -49,7 +50,7 @@ static void node_geo_exec(GeoNodeExecParams params) * every instance). Because geometry components are reference counted anyway, we can just * repurpose the original geometry sets for the output. */ if (params.output_is_required("Bounding Box")) { - geometry_set.modify_geometry_sets([&](GeometrySet &sub_geometry) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &sub_geometry) { std::optional> sub_bounds; /* Reuse the min and max calculation if this is the main "real" geometry set. */ @@ -61,7 +62,7 @@ static void node_geo_exec(GeoNodeExecParams params) } if (!sub_bounds) { - sub_geometry.remove_geometry_during_modify(); + sub_geometry.clear(); } else { const float3 scale = sub_bounds->max - sub_bounds->min; @@ -69,7 +70,7 @@ static void node_geo_exec(GeoNodeExecParams params) Mesh *mesh = geometry::create_cuboid_mesh(scale, 2, 2, 2, "uv_map"); geometry::transform_mesh(*mesh, center, math::Quaternion::identity(), float3(1)); sub_geometry.replace_mesh(mesh); - sub_geometry.keep_only_during_modify({GeometryComponent::Type::Mesh}); + sub_geometry.keep_only({GeometryComponent::Type::Mesh, GeometryComponent::Type::Edit}); } }); diff --git a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc index ce26f58a9bb..92b5b8683bb 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc @@ -10,6 +10,7 @@ #include "BKE_material.hh" #include "BKE_mesh.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_randomize.hh" #include "node_geometry_util.hh" @@ -257,7 +258,7 @@ static void node_geo_exec(GeoNodeExecParams params) #ifdef WITH_BULLET - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { Mesh *mesh = compute_hull(geometry_set); if (mesh) { geometry::debug_randomize_mesh_order(mesh); @@ -266,7 +267,9 @@ static void node_geo_exec(GeoNodeExecParams params) if (geometry_set.has_grease_pencil()) { convex_hull_grease_pencil(geometry_set); } - geometry_set.keep_only_during_modify({GeometryComponent::Type::Mesh}); + geometry_set.keep_only({GeometryComponent::Type::Mesh, + GeometryComponent::Type::Instance, + GeometryComponent::Type::Edit}); }); params.set_output("Convex Hull", std::move(geometry_set)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc index 1c212be1d61..055b916d796 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc @@ -14,6 +14,8 @@ #include "BLI_task.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_curve_fill_cc { @@ -310,8 +312,9 @@ static void node_geo_exec(GeoNodeExecParams params) Field group_index = params.extract_input>("Group ID"); const GeometryNodeCurveFillMode mode = params.extract_input("Mode"); - geometry_set.modify_geometry_sets( - [&](GeometrySet &geometry_set) { curve_fill_calculate(geometry_set, mode, group_index); }); + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry) { + curve_fill_calculate(geometry, mode, group_index); + }); params.set_output("Mesh", std::move(geometry_set)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc index b2a8188ed1b..015b5d5eacc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc @@ -7,6 +7,7 @@ #include "BKE_grease_pencil.hh" #include "GEO_fillet_curves.hh" +#include "GEO_foreach_geometry.hh" #include "node_geometry_util.hh" @@ -142,7 +143,7 @@ static void node_geo_exec(GeoNodeExecParams params) const NodeAttributeFilter &attribute_filter = params.get_attribute_filter("Curve"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (geometry_set.has_curves()) { const Curves &curves_id = *geometry_set.get_curves(); const bke::CurvesGeometry &src_curves = curves_id.geometry.wrap(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc index f71313fad05..cb5cf04c544 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc @@ -2,6 +2,7 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ +#include "GEO_foreach_geometry.hh" #include "GEO_resample_curves.hh" #include "BKE_curves.hh" @@ -91,7 +92,7 @@ static void node_geo_exec(GeoNodeExecParams params) switch (mode) { case GEO_NODE_CURVE_RESAMPLE_COUNT: { Field count = params.extract_input>("Count"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry) { if (const Curves *src_curves_id = geometry.get_curves()) { const bke::CurvesGeometry &src_curves = src_curves_id->geometry.wrap(); const bke::CurvesFieldContext field_context{*src_curves_id, AttrDomain::Curve}; @@ -123,7 +124,7 @@ static void node_geo_exec(GeoNodeExecParams params) } case GEO_NODE_CURVE_RESAMPLE_LENGTH: { Field length = params.extract_input>("Length"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry) { if (const Curves *src_curves_id = geometry.get_curves()) { const bke::CurvesGeometry &src_curves = src_curves_id->geometry.wrap(); const bke::CurvesFieldContext field_context{*src_curves_id, AttrDomain::Curve}; @@ -153,7 +154,7 @@ static void node_geo_exec(GeoNodeExecParams params) break; } case GEO_NODE_CURVE_RESAMPLE_EVALUATED: - geometry_set.modify_geometry_sets([&](GeometrySet &geometry) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry) { if (const Curves *src_curves_id = geometry.get_curves()) { const bke::CurvesGeometry &src_curves = src_curves_id->geometry.wrap(); const bke::CurvesFieldContext field_context{*src_curves_id, AttrDomain::Curve}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc index 6cac0e76132..d0b3ca1ab11 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc @@ -5,6 +5,8 @@ #include "BKE_curves.hh" #include "BKE_grease_pencil.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_curve_reverse_cc { @@ -57,7 +59,7 @@ static void node_geo_exec(GeoNodeExecParams params) GeometryComponentEditData::remember_deformed_positions_if_necessary(geometry_set); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Curves *curves_id = geometry_set.get_curves_for_write()) { bke::CurvesGeometry &curves = curves_id->geometry.wrap(); const bke::CurvesFieldContext field_context{*curves_id, AttrDomain::Curve}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc index add28f24932..5c1c7c60a6b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc @@ -9,6 +9,8 @@ #include "UI_interface_layout.hh" #include "UI_resources.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_curve_set_handle_type_cc { @@ -101,7 +103,7 @@ static void node_geo_exec(GeoNodeExecParams params) std::atomic has_curves = false; std::atomic has_bezier = false; - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Curves *curves_id = geometry_set.get_curves_for_write()) { bke::CurvesGeometry &curves = curves_id->geometry.wrap(); has_curves = true; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc index 317075ffab0..6e3a9a2fd5d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc @@ -9,6 +9,7 @@ #include "UI_interface_layout.hh" #include "UI_resources.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_set_curve_type.hh" #include "RNA_enum_types.hh" @@ -52,7 +53,7 @@ static void node_geo_exec(GeoNodeExecParams params) GeometrySet geometry_set = params.extract_input("Curve"); Field selection_field = params.extract_input>("Selection"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (!geometry_set.has_curves()) { return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc index f0f7896f524..244eae9a59a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc @@ -5,6 +5,7 @@ #include "BKE_curves.hh" #include "BKE_grease_pencil.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_subdivide_curves.hh" #include "node_geometry_util.hh" @@ -88,7 +89,7 @@ static void node_geo_exec(GeoNodeExecParams params) GeometryComponentEditData::remember_deformed_positions_if_necessary(geometry_set); const NodeAttributeFilter &attribute_filter = params.get_attribute_filter("Curve"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (geometry_set.has_curves()) { const Curves &src_curves_id = *geometry_set.get_curves(); Curves *dst_curves_id = subdivide_curves(src_curves_id, cuts_field, attribute_filter); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc index b5460722f8e..868e299d06b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc @@ -8,6 +8,7 @@ #include "BKE_grease_pencil.hh" #include "BKE_instances.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_join_geometries.hh" #include "GEO_randomize.hh" @@ -126,7 +127,7 @@ static void node_geo_exec(GeoNodeExecParams params) bke::GeometryComponentEditData::remember_deformed_positions_if_necessary(curve_set); const AttributeFilter &attribute_filter = params.get_attribute_filter("Mesh"); - curve_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(curve_set, [&](GeometrySet &geometry_set) { if (geometry_set.has_curves()) { const Curves &curves = *geometry_set.get_curves(); @@ -142,7 +143,9 @@ static void node_geo_exec(GeoNodeExecParams params) if (geometry_set.has_grease_pencil()) { grease_pencil_to_mesh(geometry_set, profile_set, scale_field, fill_caps, attribute_filter); } - geometry_set.keep_only_during_modify({GeometryComponent::Type::Mesh}); + geometry_set.keep_only({GeometryComponent::Type::Mesh, + GeometryComponent::Type::Instance, + GeometryComponent::Type::Edit}); }); params.set_output("Mesh", std::move(curve_set)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc index 1831018ab6f..ab72ef951df 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc @@ -11,6 +11,7 @@ #include "BKE_instances.hh" #include "BKE_pointcloud.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_join_geometries.hh" #include "GEO_resample_curves.hh" @@ -215,7 +216,7 @@ static void node_geo_exec(GeoNodeExecParams params) switch (mode) { case GEO_NODE_CURVE_RESAMPLE_COUNT: { const Field count = params.extract_input>("Count"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry) { if (const Curves *src_curves_id = geometry.get_curves()) { bke::CurvesGeometry dst_curves = geometry::resample_to_count( src_curves_id->geometry.wrap(), @@ -246,13 +247,15 @@ static void node_geo_exec(GeoNodeExecParams params) } layer_pointclouds_to_instances(pointcloud_by_layer, attribute_filter, geometry); } - geometry.keep_only_during_modify({bke::GeometryComponent::Type::PointCloud}); + geometry.keep_only({bke::GeometryComponent::Type::PointCloud, + bke::GeometryComponent::Type::Instance, + bke::GeometryComponent::Type::Edit}); }); break; } case GEO_NODE_CURVE_RESAMPLE_LENGTH: { const Field length = params.extract_input>("Length"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry) { if (const Curves *src_curves_id = geometry.get_curves()) { bke::CurvesGeometry dst_curves = geometry::resample_to_length( src_curves_id->geometry.wrap(), @@ -283,12 +286,14 @@ static void node_geo_exec(GeoNodeExecParams params) } layer_pointclouds_to_instances(pointcloud_by_layer, attribute_filter, geometry); } - geometry.keep_only_during_modify({bke::GeometryComponent::Type::PointCloud}); + geometry.keep_only({bke::GeometryComponent::Type::PointCloud, + bke::GeometryComponent::Type::Instance, + bke::GeometryComponent::Type::Edit}); }); break; } case GEO_NODE_CURVE_RESAMPLE_EVALUATED: { - geometry_set.modify_geometry_sets([&](GeometrySet &geometry) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry) { if (const Curves *src_curves_id = geometry.get_curves()) { bke::CurvesGeometry dst_curves = geometry::resample_to_evaluated( src_curves_id->geometry.wrap(), @@ -318,7 +323,9 @@ static void node_geo_exec(GeoNodeExecParams params) } layer_pointclouds_to_instances(pointcloud_by_layer, attribute_filter, geometry); } - geometry.keep_only_during_modify({bke::GeometryComponent::Type::PointCloud}); + geometry.keep_only({bke::GeometryComponent::Type::PointCloud, + bke::GeometryComponent::Type::Instance, + bke::GeometryComponent::Type::Edit}); }); break; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc index 6bc491c15a1..f7c60488ecd 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc @@ -10,6 +10,7 @@ #include "NOD_socket_search_link.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_trim_curves.hh" #include "NOD_rna_define.hh" @@ -219,7 +220,7 @@ static void node_geo_exec(GeoNodeExecParams params) if (mode == GEO_NODE_CURVE_SAMPLE_FACTOR) { Field start_field = params.extract_input>("Start"); Field end_field = params.extract_input>("End"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { geometry_set_curve_trim( geometry_set, mode, selection_field, start_field, end_field, attribute_filter); }); @@ -227,7 +228,7 @@ static void node_geo_exec(GeoNodeExecParams params) else if (mode == GEO_NODE_CURVE_SAMPLE_LENGTH) { Field start_field = params.extract_input>("Start_001"); Field end_field = params.extract_input>("End_001"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { geometry_set_curve_trim( geometry_set, mode, selection_field, start_field, end_field, attribute_filter); }); diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index d53a517ef73..71da28c5e92 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -7,6 +7,7 @@ #include "UI_interface_layout.hh" #include "UI_resources.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_separate_geometry.hh" #include "RNA_enum_types.hh" @@ -74,7 +75,7 @@ static void node_geo_exec(GeoNodeExecParams params) geometry::separate_geometry(geometry_set, domain, mode, selection, attribute_filter, is_error); } else { - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { bool is_error; /* Invert here because we want to keep the things not in the selection. */ geometry::separate_geometry( diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc index 35a74168bee..4371e29e8dc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc @@ -17,6 +17,7 @@ #include "BKE_volume.hh" #include "BKE_volume_grid.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_randomize.hh" #include "node_geometry_util.hh" @@ -195,9 +196,9 @@ static void node_geo_exec(GeoNodeExecParams params) threshold = params.extract_input("Threshold"); } - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (!geometry_set.has_volume()) { - geometry_set.keep_only_during_modify({GeometryComponent::Type::PointCloud}); + geometry_set.keep_only({GeometryComponent::Type::Edit}); return; } const VolumeComponent *component = geometry_set.get_component(); @@ -241,7 +242,7 @@ static void node_geo_exec(GeoNodeExecParams params) geometry::debug_randomize_point_order(pointcloud); geometry_set.replace_pointcloud(pointcloud); - geometry_set.keep_only_during_modify({GeometryComponent::Type::PointCloud}); + geometry_set.keep_only({GeometryComponent::Type::PointCloud, GeometryComponent::Type::Edit}); }); params.set_output("Points", std::move(geometry_set)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index 03d7f3c251f..57411cfe2c4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -20,6 +20,7 @@ #include "UI_interface_layout.hh" #include "UI_resources.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_randomize.hh" #include "node_geometry_util.hh" @@ -594,12 +595,12 @@ static void node_geo_exec(GeoNodeExecParams params) lazy_threading::send_hint(); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { point_distribution_calculate( geometry_set, selection_field, method, seed, attribute_outputs, params); /* Keep instances because the original geometry set may contain instances that are processed as * well. */ - geometry_set.keep_only_during_modify({GeometryComponent::Type::PointCloud}); + geometry_set.keep_only({GeometryComponent::Type::PointCloud, GeometryComponent::Type::Edit}); }); params.set_output("Points", std::move(geometry_set)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc index 6b527c4bcd4..1e14826b63a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc @@ -7,6 +7,7 @@ #include "BKE_attribute_math.hh" #include "BKE_mesh.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_randomize.hh" #include "node_geometry_util.hh" @@ -920,7 +921,7 @@ static void node_geo_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input("Mesh"); const bool keep_boundaries = params.extract_input("Keep Boundaries"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (const Mesh *mesh = geometry_set.get_mesh()) { Mesh *new_mesh = calc_dual_mesh( *mesh, keep_boundaries, params.get_attribute_filter("Dual Mesh")); diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc index 6ad53c0525f..c79204dba55 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc @@ -21,6 +21,8 @@ #include "NOD_rna_define.hh" +#include "GEO_foreach_geometry.hh" + #include "FN_multi_function_builder.hh" #include "UI_interface_layout.hh" @@ -317,8 +319,9 @@ static void duplicate_curves(GeometrySet &geometry_set, const IndexAttributes &attribute_outputs, const AttributeFilter &attribute_filter) { - geometry_set.keep_only_during_modify( - {GeometryComponent::Type::Curve, GeometryComponent::Type::GreasePencil}); + geometry_set.keep_only({GeometryComponent::Type::Curve, + GeometryComponent::Type::GreasePencil, + GeometryComponent::Type::Edit}); GeometryComponentEditData::remember_deformed_positions_if_necessary(geometry_set); if (const Curves *curves_id = geometry_set.get_curves()) { const bke::CurvesFieldContext field_context{*curves_id, AttrDomain::Curve}; @@ -463,10 +466,10 @@ static void duplicate_faces(GeometrySet &geometry_set, const AttributeFilter &attribute_filter) { if (!geometry_set.has_mesh()) { - geometry_set.remove_geometry_during_modify(); + geometry_set.clear(); return; } - geometry_set.keep_only_during_modify({GeometryComponent::Type::Mesh}); + geometry_set.keep_only({GeometryComponent::Type::Mesh, GeometryComponent::Type::Edit}); const Mesh &mesh = *geometry_set.get_mesh(); const OffsetIndices faces = mesh.faces(); @@ -649,7 +652,7 @@ static void duplicate_edges(GeometrySet &geometry_set, const AttributeFilter &attribute_filter) { if (!geometry_set.has_mesh()) { - geometry_set.remove_geometry_during_modify(); + geometry_set.clear(); return; }; const Mesh &mesh = *geometry_set.get_mesh(); @@ -994,8 +997,8 @@ static void duplicate_points(GeometrySet &geometry_set, break; } } - component_types.append(GeometryComponent::Type::Instance); - geometry_set.keep_only_during_modify(component_types); + component_types.append(GeometryComponent::Type::Edit); + geometry_set.keep_only(component_types); } /** \} */ @@ -1015,7 +1018,7 @@ static void duplicate_layers(GeometrySet &geometry_set, geometry_set.clear(); return; } - geometry_set.keep_only_during_modify({GeometryComponent::Type::GreasePencil}); + geometry_set.keep_only({GeometryComponent::Type::GreasePencil, GeometryComponent::Type::Edit}); GeometryComponentEditData::remember_deformed_positions_if_necessary(geometry_set); const GreasePencil &src_grease_pencil = *geometry_set.get_grease_pencil(); @@ -1179,7 +1182,7 @@ static void node_geo_exec(GeoNodeExecParams params) geometry_set, count_field, selection_field, attribute_outputs, attribute_filter); } else { - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { switch (duplicate_domain) { case AttrDomain::Curve: duplicate_curves( diff --git a/source/blender/nodes/geometry/nodes/node_geo_edge_paths_to_curves.cc b/source/blender/nodes/geometry/nodes/node_geo_edge_paths_to_curves.cc index f16ec24514d..a6aad1c4e2b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_edge_paths_to_curves.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_edge_paths_to_curves.cc @@ -6,6 +6,7 @@ #include "DNA_mesh_types.h" +#include "GEO_foreach_geometry.hh" #include "GEO_mesh_to_curve.hh" #include "node_geometry_util.hh" @@ -72,10 +73,10 @@ static void node_geo_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input("Mesh"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { const Mesh *mesh = geometry_set.get_mesh(); if (mesh == nullptr) { - geometry_set.keep_only({GeometryComponent::Type::Instance}); + geometry_set.keep_only({GeometryComponent::Type::Edit}); return; } @@ -88,13 +89,13 @@ static void node_geo_exec(GeoNodeExecParams params) IndexMask start_verts = evaluator.get_evaluated_as_mask(1); if (start_verts.is_empty()) { - geometry_set.keep_only({GeometryComponent::Type::Instance}); + geometry_set.keep_only({GeometryComponent::Type::Edit}); return; } geometry_set.replace_curves(edge_paths_to_curves_convert( *mesh, start_verts, next_vert, params.get_attribute_filter("Curves"))); - geometry_set.keep_only({GeometryComponent::Type::Curve, GeometryComponent::Type::Instance}); + geometry_set.keep_only({GeometryComponent::Type::Curve, GeometryComponent::Type::Edit}); }); params.set_output("Curves", std::move(geometry_set)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_edge_split.cc b/source/blender/nodes/geometry/nodes/node_geo_edge_split.cc index 4c3f77c32bc..e60e4386d45 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_edge_split.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_edge_split.cc @@ -4,6 +4,7 @@ #include "DNA_mesh_types.h" +#include "GEO_foreach_geometry.hh" #include "GEO_mesh_split_edges.hh" #include "node_geometry_util.hh" @@ -27,7 +28,7 @@ static void node_geo_exec(GeoNodeExecParams params) const Field selection_field = params.extract_input>("Selection"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (const Mesh *mesh = geometry_set.get_mesh()) { const bke::MeshFieldContext field_context{*mesh, AttrDomain::Edge}; fn::FieldEvaluator selection_evaluator{field_context, mesh->edges_num}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index ea00b7c7ad9..296b873c77e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -17,6 +17,7 @@ #include "BKE_mesh_mapping.hh" #include "BKE_mesh_runtime.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_mesh_selection.hh" #include "GEO_randomize.hh" @@ -1476,7 +1477,7 @@ static void node_geo_exec(GeoNodeExecParams params) const NodeAttributeFilter &attribute_filter = params.get_attribute_filter("Mesh"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Mesh *mesh = geometry_set.get_mesh_for_write()) { switch (mode) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc index 9c96fd35165..fef3998ace7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc @@ -4,6 +4,8 @@ #include "BKE_mesh.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_flip_faces_cc { @@ -25,7 +27,7 @@ static void node_geo_exec(GeoNodeExecParams params) const Field selection_field = params.extract_input>("Selection"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Mesh *mesh = geometry_set.get_mesh_for_write()) { const bke::MeshFieldContext field_context(*mesh, AttrDomain::Face); fn::FieldEvaluator evaluator(field_context, mesh->faces_num); diff --git a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc index e7cca259dd6..febd2ef81d8 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc @@ -11,6 +11,7 @@ #include "BKE_grease_pencil.hh" #include "BKE_instances.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_join_geometries.hh" #include "node_geometry_util.hh" @@ -187,16 +188,8 @@ static void node_geo_exec(GeoNodeExecParams params) instance.ensure_owns_direct_data(); const NodeAttributeFilter &attribute_filter = params.get_attribute_filter("Instances"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { - /* It's important not to invalidate the existing #InstancesComponent because it owns references - * to other geometry sets that are processed by this node. */ - InstancesComponent &instances_component = - geometry_set.get_component_for_write(); - bke::Instances *dst_instances = instances_component.get_for_write(); - if (dst_instances == nullptr) { - dst_instances = new bke::Instances(); - instances_component.replace(dst_instances); - } + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { + bke::Instances *dst_instances = new bke::Instances(); const Array types{GeometryComponent::Type::Mesh, GeometryComponent::Type::PointCloud, @@ -226,7 +219,7 @@ static void node_geo_exec(GeoNodeExecParams params) if (geometry_set.has_grease_pencil()) { using namespace bke::greasepencil; const GreasePencil &grease_pencil = *geometry_set.get_grease_pencil(); - bke::Instances *instances = new bke::Instances(); + bke::Instances *instances_per_layer = new bke::Instances(); for (const int layer_index : grease_pencil.layers().index_range()) { const Layer &layer = grease_pencil.layer(layer_index); const Drawing *drawing = grease_pencil.get_eval_drawing(layer); @@ -239,8 +232,8 @@ static void node_geo_exec(GeoNodeExecParams params) /* Add an empty reference so the number of layers and instances match. * This makes it easy to reconstruct the layers afterwards and keep their attributes. * Although in this particular case we don't propagate the attributes. */ - const int handle = instances->add_reference(bke::InstanceReference()); - instances->add_instance(handle, layer_transform); + const int handle = instances_per_layer->add_reference(bke::InstanceReference()); + instances_per_layer->add_instance(handle, layer_transform); continue; } /* TODO: Attributes are not propagating from the curves or the points. */ @@ -254,25 +247,23 @@ static void node_geo_exec(GeoNodeExecParams params) params, attributes_to_propagate); GeometrySet temp_set = GeometrySet::from_instances(layer_instances); - const int handle = instances->add_reference(bke::InstanceReference{temp_set}); - instances->add_instance(handle, layer_transform); + const int handle = instances_per_layer->add_reference(bke::InstanceReference{temp_set}); + instances_per_layer->add_instance(handle, layer_transform); } bke::copy_attributes(geometry_set.get_grease_pencil()->attributes(), bke::AttrDomain::Layer, bke::AttrDomain::Instance, attribute_filter, - instances->attributes_for_write()); + instances_per_layer->attributes_for_write()); GeometrySet new_instances = geometry::join_geometries( - {GeometrySet::from_instances(dst_instances, bke::GeometryOwnershipType::Editable), - GeometrySet::from_instances(instances)}, + {GeometrySet::from_instances(dst_instances), + GeometrySet::from_instances(instances_per_layer)}, attribute_filter); - instances_component.replace( - new_instances.get_component_for_write().release()); - - geometry_set.replace_grease_pencil(nullptr); + dst_instances = new_instances.get_component_for_write().release(); } - geometry_set.remove_geometry_during_modify(); + geometry_set.keep_only({GeometryComponent::Type::Edit}); + geometry_set.replace_instances(dst_instances); }); /* Unused references may have been added above. Remove those now so that other nodes don't diff --git a/source/blender/nodes/geometry/nodes/node_geo_material_replace.cc b/source/blender/nodes/geometry/nodes/node_geo_material_replace.cc index 8359fe57f54..7721b40d529 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_material_replace.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_material_replace.cc @@ -6,6 +6,8 @@ #include "DNA_mesh_types.h" +#include "GEO_foreach_geometry.hh" + #include "BKE_grease_pencil.hh" namespace blender::nodes::node_geo_material_replace_cc { @@ -40,7 +42,7 @@ static void node_geo_exec(GeoNodeExecParams params) GeometrySet geometry_set = params.extract_input("Geometry"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Mesh *mesh = geometry_set.get_mesh_for_write()) { replace_materials({mesh->mat, mesh->totcol}, old_material, new_material); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_merge_by_distance.cc b/source/blender/nodes/geometry/nodes/node_geo_merge_by_distance.cc index d862442ac04..7bce3ae8c64 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_merge_by_distance.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_merge_by_distance.cc @@ -5,6 +5,7 @@ #include "DNA_mesh_types.h" #include "DNA_pointcloud_types.h" +#include "GEO_foreach_geometry.hh" #include "GEO_mesh_merge_by_distance.hh" #include "GEO_point_merge_by_distance.hh" @@ -103,7 +104,7 @@ static void node_geo_exec(GeoNodeExecParams params) const Field selection = params.extract_input>("Selection"); const float merge_distance = params.extract_input("Distance"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (const PointCloud *pointcloud = geometry_set.get_pointcloud()) { PointCloud *result = pointcloud_merge_by_distance( *pointcloud, merge_distance, selection, params.get_attribute_filter("Geometry")); diff --git a/source/blender/nodes/geometry/nodes/node_geo_merge_layers.cc b/source/blender/nodes/geometry/nodes/node_geo_merge_layers.cc index 889af551f9c..7bf53396174 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_merge_layers.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_merge_layers.cc @@ -4,6 +4,7 @@ #include "node_geometry_util.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_merge_layers.hh" #include "BKE_grease_pencil.hh" @@ -170,8 +171,9 @@ static void node_geo_exec(GeoNodeExecParams params) const NodeAttributeFilter attribute_filter = params.get_attribute_filter("Grease Pencil"); - main_geometry.modify_geometry_sets( - [&](GeometrySet &geometry) { merge_layers(geometry, storage, params, attribute_filter); }); + geometry::foreach_real_geometry(main_geometry, [&](GeometrySet &geometry) { + merge_layers(geometry, storage, params, attribute_filter); + }); params.set_output("Grease Pencil", std::move(main_geometry)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc index f40ea7930bf..6e97703b36e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc @@ -5,6 +5,7 @@ #include "BKE_subdiv.hh" #include "BKE_subdiv_mesh.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_randomize.hh" #include "node_geometry_util.hh" @@ -72,7 +73,7 @@ static void node_geo_exec(GeoNodeExecParams params) return; } - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (const Mesh *mesh = geometry_set.get_mesh()) { geometry_set.replace_mesh(simple_subdivide_mesh(*mesh, level)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc index f782b35c196..96071ade5a8 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc @@ -6,6 +6,7 @@ #include "NOD_rna_define.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_mesh_to_curve.hh" #include "UI_interface_c.hh" @@ -39,10 +40,10 @@ static void node_geo_exec(GeoNodeExecParams params) const Mode mode = Mode(params.node().custom1); GeometrySet geometry_set = params.extract_input("Mesh"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { const Mesh *mesh = geometry_set.get_mesh(); if (mesh == nullptr) { - geometry_set.remove_geometry_during_modify(); + geometry_set.keep_only({GeometryComponent::Type::Edit}); return; } @@ -54,7 +55,7 @@ static void node_geo_exec(GeoNodeExecParams params) evaluator.evaluate(); const IndexMask selection = evaluator.get_evaluated_as_mask(0); if (selection.is_empty()) { - geometry_set.remove_geometry_during_modify(); + geometry_set.keep_only({GeometryComponent::Type::Edit}); return; } @@ -70,7 +71,7 @@ static void node_geo_exec(GeoNodeExecParams params) evaluator.evaluate(); const IndexMask selection = evaluator.get_evaluated_as_mask(0); if (selection.is_empty()) { - geometry_set.remove_geometry_during_modify(); + geometry_set.keep_only({GeometryComponent::Type::Edit}); return; } @@ -80,7 +81,7 @@ static void node_geo_exec(GeoNodeExecParams params) break; } } - geometry_set.keep_only_during_modify({GeometryComponent::Type::Curve}); + geometry_set.keep_only({GeometryComponent::Type::Curve, GeometryComponent::Type::Edit}); }); params.set_output("Curve", std::move(geometry_set)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc index 85b5c28299e..7bc058897c9 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc @@ -16,6 +16,8 @@ #include "UI_interface_layout.hh" #include "UI_resources.hh" +#include "GEO_foreach_geometry.hh" + #include "FN_multi_function_builder.hh" #include "node_geometry_util.hh" @@ -60,12 +62,12 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set, { const Mesh *mesh = geometry_set.get_mesh(); if (mesh == nullptr) { - geometry_set.remove_geometry_during_modify(); + geometry_set.keep_only({GeometryComponent::Type::Edit}); return; } const int domain_size = mesh->attributes().domain_size(domain); if (domain_size == 0) { - geometry_set.remove_geometry_during_modify(); + geometry_set.keep_only({GeometryComponent::Type::Edit}); return; } const AttributeAccessor src_attributes = mesh->attributes(); @@ -138,7 +140,7 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set, } geometry_set.replace_pointcloud(pointcloud); - geometry_set.keep_only_during_modify({GeometryComponent::Type::PointCloud}); + geometry_set.keep_only({GeometryComponent::Type::PointCloud, GeometryComponent::Type::Edit}); } static void node_geo_exec(GeoNodeExecParams params) @@ -161,7 +163,7 @@ static void node_geo_exec(GeoNodeExecParams params) const NodeAttributeFilter &attribute_filter = params.get_attribute_filter("Points"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { switch (mode) { case GEO_NODE_MESH_TO_POINTS_VERTICES: geometry_set_mesh_to_points(geometry_set, diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_volume.cc index b880a89be0f..9722d8751f3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_volume.cc @@ -9,6 +9,7 @@ #include "BKE_lib_id.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_mesh_to_volume.hh" #include "NOD_rna_define.hh" @@ -127,11 +128,11 @@ static void node_geo_exec(GeoNodeExecParams params) { #ifdef WITH_OPENVDB GeometrySet geometry_set(params.extract_input("Mesh")); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (geometry_set.has_mesh()) { Volume *volume = create_volume_from_mesh(*geometry_set.get_mesh(), params); geometry_set.replace_volume(volume); - geometry_set.keep_only_during_modify({GeometryComponent::Type::Volume}); + geometry_set.keep_only({GeometryComponent::Type::Volume, GeometryComponent::Type::Edit}); } }); params.set_output("Volume", std::move(geometry_set)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_curves.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_curves.cc index ddb49ed5932..9d56ae04e9f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_points_to_curves.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_curves.cc @@ -14,6 +14,7 @@ #include "BLI_sort.hh" #include "BLI_task.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_randomize.hh" #include "BKE_geometry_set.hh" @@ -174,14 +175,14 @@ static void node_geo_exec(GeoNodeExecParams params) const Field weight_field = params.extract_input>("Weight"); const NodeAttributeFilter attribute_filter = params.get_attribute_filter("Curves"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { geometry_set.replace_curves(nullptr); if (const PointCloud *points = geometry_set.get_pointcloud()) { Curves *curves_id = curves_from_points( *points, group_id_field, weight_field, attribute_filter); geometry_set.replace_curves(curves_id); } - geometry_set.keep_only_during_modify({GeometryComponent::Type::Curve}); + geometry_set.keep_only({GeometryComponent::Type::Curve, GeometryComponent::Type::Edit}); }); params.set_output("Curves", std::move(geometry_set)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc index c79890154c2..91f0a210de3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc @@ -9,6 +9,8 @@ #include "BKE_customdata.hh" #include "BKE_mesh.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_points_to_vertices_cc { @@ -29,11 +31,11 @@ static void geometry_set_points_to_vertices(GeometrySet &geometry_set, { const PointCloud *points = geometry_set.get_pointcloud(); if (points == nullptr) { - geometry_set.remove_geometry_during_modify(); + geometry_set.keep_only({GeometryComponent::Type::Edit}); return; } if (points->totpoint == 0) { - geometry_set.remove_geometry_during_modify(); + geometry_set.keep_only({GeometryComponent::Type::Edit}); return; } @@ -85,7 +87,7 @@ static void geometry_set_points_to_vertices(GeometrySet &geometry_set, mesh->tag_overlapping_none(); geometry_set.replace_mesh(mesh); - geometry_set.keep_only_during_modify({GeometryComponent::Type::Mesh}); + geometry_set.keep_only({GeometryComponent::Type::Mesh, GeometryComponent::Type::Edit}); } static void node_geo_exec(GeoNodeExecParams params) @@ -93,7 +95,7 @@ static void node_geo_exec(GeoNodeExecParams params) GeometrySet geometry_set = params.extract_input("Points"); Field selection_field = params.extract_input>("Selection"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { geometry_set_points_to_vertices( geometry_set, selection_field, params.get_attribute_filter("Mesh")); }); diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc index 5b4eb64c661..119ca48ddc6 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc @@ -12,6 +12,7 @@ #include "node_geometry_util.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_points_to_volume.hh" #include "BKE_lib_id.hh" @@ -115,7 +116,7 @@ static void initialize_volume_component_from_points(GeoNodeExecParams ¶ms, blender::geometry::fog_volume_grid_add_from_points( volume, "density", positions, radii, voxel_size, density); - r_geometry_set.keep_only_during_modify({GeometryComponent::Type::Volume}); + r_geometry_set.keep_only({GeometryComponent::Type::Volume, GeometryComponent::Type::Edit}); r_geometry_set.replace_volume(volume); } @@ -172,7 +173,7 @@ static void node_geo_exec(GeoNodeExecParams params) { #ifdef WITH_OPENVDB GeometrySet geometry_set = params.extract_input("Points"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { initialize_volume_component_from_points(params, geometry_set); }); params.set_output("Volume", std::move(geometry_set)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc index 0abafa96766..a52719446d4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc @@ -2,6 +2,7 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BKE_instances.hh" #include "node_geometry_util.hh" #include @@ -36,6 +37,82 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input("Name").is_attribute_name().hide_label(); } +struct RemoveAttributeParams { + PatternMode pattern_mode; + std::string pattern; + std::string wildcard_prefix; + std::string wildcard_suffix; + + Set removed_attributes; + Set failed_attributes; +}; + +static void remove_attributes_recursive(GeometrySet &geometry_set, RemoveAttributeParams ¶ms) +{ + for (const GeometryComponent::Type type : {GeometryComponent::Type::Mesh, + GeometryComponent::Type::PointCloud, + GeometryComponent::Type::Curve, + GeometryComponent::Type::Instance, + GeometryComponent::Type::GreasePencil}) + { + if (!geometry_set.has(type)) { + continue; + } + /* First check if the attribute exists before getting write access, + * to avoid potentially expensive unnecessary copies. */ + const GeometryComponent &read_only_component = *geometry_set.get_component(type); + Vector attributes_to_remove; + switch (params.pattern_mode) { + case PatternMode::Exact: { + if (read_only_component.attributes()->contains(params.pattern)) { + attributes_to_remove.append(params.pattern); + } + break; + } + case PatternMode::Wildcard: { + read_only_component.attributes()->foreach_attribute([&](const bke::AttributeIter &iter) { + const StringRef attribute_name = iter.name; + if (bke::attribute_name_is_anonymous(attribute_name)) { + return; + } + if (attribute_name.startswith(params.wildcard_prefix) && + attribute_name.endswith(params.wildcard_suffix)) + { + attributes_to_remove.append(attribute_name); + } + }); + + break; + } + } + if (attributes_to_remove.is_empty()) { + break; + } + + GeometryComponent &component = geometry_set.get_component_for_write(type); + for (const StringRef attribute_name : attributes_to_remove) { + if (!bke::allow_procedural_attribute_access(attribute_name)) { + continue; + } + if (component.attributes_for_write()->remove(attribute_name)) { + params.removed_attributes.add(attribute_name); + } + else { + params.failed_attributes.add(attribute_name); + } + } + } + + if (bke::Instances *instances = geometry_set.get_instances_for_write()) { + instances->ensure_geometry_instances(); + for (bke::InstanceReference &reference : instances->references_for_write()) { + if (reference.type() == bke::InstanceReference::Type::GeometrySet) { + remove_attributes_recursive(reference.geometry_set(), params); + } + } + } +} + static void node_geo_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input("Geometry"); @@ -44,6 +121,7 @@ static void node_geo_exec(GeoNodeExecParams params) params.set_output("Geometry", std::move(geometry_set)); return; } + PatternMode pattern_mode = params.get_input("Pattern Mode"); if (pattern_mode == PatternMode::Wildcard) { const int wildcard_count = Span(pattern.c_str(), pattern.size()).count('*'); @@ -58,83 +136,24 @@ static void node_geo_exec(GeoNodeExecParams params) } } - StringRef wildcard_prefix; - StringRef wildcard_suffix; + RemoveAttributeParams removal_params; + removal_params.pattern_mode = pattern_mode; + removal_params.pattern = pattern; if (pattern_mode == PatternMode::Wildcard) { const int wildcard_index = pattern.find('*'); - wildcard_prefix = StringRef(pattern).substr(0, wildcard_index); - wildcard_suffix = StringRef(pattern).substr(wildcard_index + 1); + removal_params.wildcard_prefix = StringRef(pattern).substr(0, wildcard_index); + removal_params.wildcard_suffix = StringRef(pattern).substr(wildcard_index + 1); } - Mutex attribute_log_mutex; - Set removed_attributes; - Set failed_attributes; + remove_attributes_recursive(geometry_set, removal_params); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { - for (const GeometryComponent::Type type : {GeometryComponent::Type::Mesh, - GeometryComponent::Type::PointCloud, - GeometryComponent::Type::Curve, - GeometryComponent::Type::Instance, - GeometryComponent::Type::GreasePencil}) - { - if (!geometry_set.has(type)) { - continue; - } - /* First check if the attribute exists before getting write access, - * to avoid potentially expensive unnecessary copies. */ - const GeometryComponent &read_only_component = *geometry_set.get_component(type); - Vector attributes_to_remove; - switch (pattern_mode) { - case PatternMode::Exact: { - if (read_only_component.attributes()->contains(pattern)) { - attributes_to_remove.append(pattern); - } - break; - } - case PatternMode::Wildcard: { - read_only_component.attributes()->foreach_attribute([&](const bke::AttributeIter &iter) { - const StringRef attribute_name = iter.name; - if (bke::attribute_name_is_anonymous(attribute_name)) { - return; - } - if (attribute_name.startswith(wildcard_prefix) && - attribute_name.endswith(wildcard_suffix)) - { - attributes_to_remove.append(attribute_name); - } - }); - - break; - } - } - if (attributes_to_remove.is_empty()) { - break; - } - - GeometryComponent &component = geometry_set.get_component_for_write(type); - for (const StringRef attribute_name : attributes_to_remove) { - if (!bke::allow_procedural_attribute_access(attribute_name)) { - continue; - } - if (component.attributes_for_write()->remove(attribute_name)) { - std::lock_guard lock{attribute_log_mutex}; - removed_attributes.add(attribute_name); - } - else { - std::lock_guard lock{attribute_log_mutex}; - failed_attributes.add(attribute_name); - } - } - } - }); - - for (const StringRef attribute_name : removed_attributes) { + for (const StringRef attribute_name : removal_params.removed_attributes) { params.used_named_attribute(attribute_name, NamedAttributeUsage::Remove); } - if (!failed_attributes.is_empty()) { + if (!removal_params.failed_attributes.is_empty()) { Vector quoted_attribute_names; - for (const StringRef attribute_name : failed_attributes) { + for (const StringRef attribute_name : removal_params.failed_attributes) { quoted_attribute_names.append(fmt::format("\"{}\"", attribute_name)); } const std::string message = fmt::format( @@ -142,7 +161,7 @@ static void node_geo_exec(GeoNodeExecParams params) fmt::join(quoted_attribute_names, ", ")); params.error_message_add(NodeWarningType::Warning, message); } - else if (removed_attributes.is_empty() && pattern_mode == PatternMode::Exact) { + else if (removal_params.removed_attributes.is_empty() && pattern_mode == PatternMode::Exact) { const std::string message = fmt::format(fmt::runtime(TIP_("Attribute does not exist: \"{}\"")), pattern); params.error_message_add(NodeWarningType::Warning, message); diff --git a/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc index b4783642f12..22b4bfad1bf 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc @@ -17,6 +17,7 @@ #include "UI_interface_layout.hh" #include "UI_resources.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_mesh_selection.hh" #include "NOD_rna_define.hh" @@ -474,7 +475,7 @@ static void node_geo_exec(GeoNodeExecParams params) const Field scale_field = params.extract_input>("Scale"); const Field center_field = params.extract_input>("Center"); - geometry.modify_geometry_sets([&](GeometrySet &geometry) { + geometry::foreach_real_geometry(geometry, [&](GeometrySet &geometry) { if (Mesh *mesh = geometry.get_mesh_for_write()) { const bke::MeshFieldContext context{*mesh, domain}; FieldEvaluator evaluator{context, mesh->attributes().domain_size(domain)}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_separate_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_separate_geometry.cc index 7ce4276ee71..0253404e178 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_separate_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_separate_geometry.cc @@ -9,6 +9,7 @@ #include "RNA_enum_types.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_separate_geometry.hh" #include "node_geometry_util.hh" @@ -68,7 +69,7 @@ static void node_geo_exec(GeoNodeExecParams params) is_error); } else { - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { geometry::separate_geometry(geometry_set, domain, GEO_NODE_DELETE_GEOMETRY_MODE_ALL, diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc index 285f7936c90..0bf1e783b71 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc @@ -15,6 +15,8 @@ #include "RNA_enum_types.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_set_curve_handles_cc { @@ -176,7 +178,7 @@ static void node_geo_exec(GeoNodeExecParams params) std::atomic has_curves = false; std::atomic has_bezier = false; - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Curves *curves_id = geometry_set.get_curves_for_write()) { bke::CurvesGeometry &curves = curves_id->geometry.wrap(); has_curves = true; diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_normal.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_normal.cc index f53e2a4e473..91997fd639d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_normal.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_normal.cc @@ -7,6 +7,8 @@ #include "RNA_enum_types.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_set_curve_normal_cc { @@ -90,7 +92,7 @@ static void node_geo_exec(GeoNodeExecParams params) custom_normal = params.extract_input>("Normal"); } - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Curves *curves_id = geometry_set.get_curves_for_write()) { bke::CurvesGeometry &curves = curves_id->geometry.wrap(); set_curve_normal(curves, diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc index a8e6b17f6dc..0f8fee23bb3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc @@ -5,6 +5,8 @@ #include "BKE_curves.hh" #include "BKE_grease_pencil.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_set_curve_radius_cc { @@ -44,7 +46,7 @@ static void node_geo_exec(GeoNodeExecParams params) const Field selection = params.extract_input>("Selection"); const Field radius = params.extract_input>("Radius"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Curves *curves_id = geometry_set.get_curves_for_write()) { bke::CurvesGeometry &curves = curves_id->geometry.wrap(); const bke::CurvesFieldContext field_context(*curves_id, AttrDomain::Point); diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc index e82fce6a52e..143c4f61251 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc @@ -5,6 +5,8 @@ #include "BKE_curves.hh" #include "BKE_grease_pencil.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_set_curve_tilt_cc { @@ -58,7 +60,7 @@ static void node_geo_exec(GeoNodeExecParams params) const Field selection = params.extract_input>("Selection"); const Field tilt = params.extract_input>("Tilt"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Curves *curves_id = geometry_set.get_curves_for_write()) { bke::CurvesGeometry &curves = curves_id->geometry.wrap(); const bke::CurvesFieldContext field_context(*curves_id, AttrDomain::Point); diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_grease_pencil_color.cc b/source/blender/nodes/geometry/nodes/node_geo_set_grease_pencil_color.cc index 9b512e7854e..9796c28d434 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_grease_pencil_color.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_grease_pencil_color.cc @@ -10,6 +10,8 @@ #include "NOD_rna_define.hh" +#include "GEO_foreach_geometry.hh" + #include "RNA_enum_types.hh" #include "node_geometry_util.hh" @@ -62,7 +64,7 @@ static void node_geo_exec(GeoNodeExecParams params) const StringRef color_attr_name = domain == AttrDomain::Point ? "vertex_color" : "fill_color"; const StringRef opacity_attr_name = domain == AttrDomain::Point ? "opacity" : "fill_opacity"; - geometry_set.modify_geometry_sets([&](GeometrySet &geometry) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry) { if (GreasePencil *grease_pencil = geometry.get_grease_pencil_for_write()) { using namespace bke::greasepencil; for (const int layer_index : grease_pencil->layers().index_range()) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_grease_pencil_depth_mode.cc b/source/blender/nodes/geometry/nodes/node_geo_set_grease_pencil_depth_mode.cc index b8ea85a738e..62b1a22794a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_grease_pencil_depth_mode.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_grease_pencil_depth_mode.cc @@ -11,6 +11,8 @@ #include "RNA_enum_types.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_grease_pencil_set_depth_mode { @@ -40,7 +42,7 @@ static void node_geo_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input("Grease Pencil"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry) { if (GreasePencil *grease_pencil = geometry.get_grease_pencil_for_write()) { SET_FLAG_FROM_TEST(grease_pencil->flag, params.node().custom1 == GREASE_PENCIL_STROKE_ORDER_3D, diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_grease_pencil_softness.cc b/source/blender/nodes/geometry/nodes/node_geo_set_grease_pencil_softness.cc index 46d06887409..a637b3957cf 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_grease_pencil_softness.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_grease_pencil_softness.cc @@ -5,6 +5,8 @@ #include "BKE_curves.hh" #include "BKE_grease_pencil.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_set_grease_pencil_softness_cc { @@ -28,7 +30,7 @@ static void node_geo_exec(GeoNodeExecParams params) const Field selection = params.extract_input>("Selection"); const Field softness = params.extract_input>("Softness"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry) { if (GreasePencil *grease_pencil = geometry.get_grease_pencil_for_write()) { using namespace bke::greasepencil; for (const int layer_index : grease_pencil->layers().index_range()) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_material.cc b/source/blender/nodes/geometry/nodes/node_geo_set_material.cc index 6600a0239d4..29a7cbd6c9e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_material.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_material.cc @@ -13,6 +13,8 @@ #include "BKE_grease_pencil.hh" #include "BKE_material.hh" +#include "GEO_foreach_geometry.hh" + namespace blender::nodes::node_geo_set_material_cc { static void node_declare(NodeDeclarationBuilder &b) @@ -83,7 +85,7 @@ static void node_geo_exec(GeoNodeExecParams params) bool volume_selection_warning = false; bool curves_selection_warning = false; - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Mesh *mesh = geometry_set.get_mesh_for_write()) { if (mesh->faces_num == 0) { if (mesh->verts_num > 0) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc b/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc index cc2e218d44d..2ba24b17086 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc @@ -10,6 +10,8 @@ #include "BKE_curves.hh" #include "BKE_grease_pencil.hh" +#include "GEO_foreach_geometry.hh" + namespace blender::nodes::node_geo_set_material_index_cc { static void node_declare(NodeDeclarationBuilder &b) @@ -50,7 +52,7 @@ static void node_geo_exec(GeoNodeExecParams params) const Field selection = params.extract_input>("Selection"); const Field material_index = params.extract_input>("Material Index"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Mesh *mesh = geometry_set.get_mesh_for_write()) { bke::try_capture_field_on_geometry(mesh->attributes_for_write(), bke::MeshFieldContext(*mesh, AttrDomain::Face), diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_mesh_normal.cc b/source/blender/nodes/geometry/nodes/node_geo_set_mesh_normal.cc index d1b05979957..fba7c0824e4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_mesh_normal.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_mesh_normal.cc @@ -9,6 +9,8 @@ #include "NOD_rna_define.hh" +#include "GEO_foreach_geometry.hh" + #include "RNA_enum_types.hh" #include "node_geometry_util.hh" @@ -76,7 +78,7 @@ static void node_geo_exec(GeoNodeExecParams params) const bool remove_custom = params.extract_input("Remove Custom"); const fn::Field sharp_edge = params.extract_input>("Edge Sharpness"); const fn::Field sharp_face = params.extract_input>("Face Sharpness"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Mesh *mesh = geometry_set.get_mesh_for_write()) { /* Evaluate both fields before storing the result to avoid one attribute change * potentially affecting the other field evaluation. */ @@ -129,7 +131,7 @@ static void node_geo_exec(GeoNodeExecParams params) } case Mode::Free: { const fn::Field custom_normal = params.extract_input>("Custom Normal"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Mesh *mesh = geometry_set.get_mesh_for_write()) { const bke::AttrDomain domain = bke::AttrDomain(node.custom2); bke::try_capture_field_on_geometry(mesh->attributes_for_write(), @@ -144,7 +146,7 @@ static void node_geo_exec(GeoNodeExecParams params) } case Mode::CornerFanSpace: { const fn::Field custom_normal = params.extract_input>("Custom Normal"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Mesh *mesh = geometry_set.get_mesh_for_write()) { const bke::MeshFieldContext context(*mesh, bke::AttrDomain::Corner); fn::FieldEvaluator evaluator(context, mesh->corners_num); diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc b/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc index b25bb74f1c4..20f5f2aab0d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc @@ -4,6 +4,8 @@ #include "DNA_pointcloud_types.h" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_set_point_radius_cc { @@ -30,7 +32,7 @@ static void node_geo_exec(GeoNodeExecParams params) const Field selection = params.extract_input>("Selection"); const Field radius = params.extract_input>("Radius"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (PointCloud *pointcloud = geometry_set.get_pointcloud_for_write()) { bke::try_capture_field_on_geometry(pointcloud->attributes_for_write(), bke::PointCloudFieldContext(*pointcloud), diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc b/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc index 72e54079d91..42b548f1f78 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc @@ -11,6 +11,8 @@ #include "RNA_enum_types.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_set_shade_smooth_cc { @@ -89,7 +91,7 @@ static void node_geo_exec(GeoNodeExecParams params) const Field selection = params.extract_input>("Selection"); const Field smooth_field = params.extract_input>("Shade Smooth"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Mesh *mesh = geometry_set.get_mesh_for_write()) { set_sharp(*mesh, domain, diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc b/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc index b563e9db3d8..0aefa525d13 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc @@ -5,6 +5,8 @@ #include "BKE_curves.hh" #include "BKE_grease_pencil.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_set_spline_cyclic_cc { @@ -58,7 +60,7 @@ static void node_geo_exec(GeoNodeExecParams params) const Field selection = params.extract_input>("Selection"); const Field cyclic = params.extract_input>("Cyclic"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Curves *curves_id = geometry_set.get_curves_for_write()) { bke::CurvesGeometry &curves = curves_id->geometry.wrap(); const bke::CurvesFieldContext field_context{*curves_id, AttrDomain::Curve}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc b/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc index 5db9293617a..f97962fd07a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc @@ -5,6 +5,8 @@ #include "BKE_curves.hh" #include "BKE_grease_pencil.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_set_spline_resolution_cc { @@ -59,7 +61,7 @@ static void node_geo_exec(GeoNodeExecParams params) const Field selection = params.extract_input>("Selection"); const Field resolution = params.extract_input>("Resolution"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (Curves *curves_id = geometry_set.get_curves_for_write()) { bke::CurvesGeometry &curves = curves_id->geometry.wrap(); const bke::CurvesFieldContext field_context(*curves_id, AttrDomain::Curve); diff --git a/source/blender/nodes/geometry/nodes/node_geo_sort_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_sort_elements.cc index f5bf3e15651..d380497e7aa 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sort_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sort_elements.cc @@ -12,6 +12,7 @@ #include "BLI_sort.hh" #include "BLI_task.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_reorder.hh" #include "NOD_rna_define.hh" @@ -224,7 +225,7 @@ static void node_geo_exec(GeoNodeExecParams params) } } else { - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { for (const auto [type, domains] : geometry::components_supported_reordering().items()) { const bke::GeometryComponent *src_component = geometry_set.get_component(type); if (src_component == nullptr || src_component->is_empty()) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc index 2e2465f5e4f..29dc4f8c314 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc @@ -18,6 +18,8 @@ #include "NOD_rna_define.hh" #include "NOD_socket_search_link.hh" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" #include @@ -145,7 +147,7 @@ static void node_geo_exec(GeoNodeExecParams params) } } else { - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { for (const GeometryComponent::Type type : {GeometryComponent::Type::Mesh, GeometryComponent::Type::PointCloud, GeometryComponent::Type::Curve, diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc index b6c27c79569..a0e1e2cc819 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc @@ -12,6 +12,7 @@ #include "RNA_enum_types.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_randomize.hh" #include "FN_multi_function_builder.hh" @@ -194,7 +195,7 @@ static void node_geo_exec(GeoNodeExecParams params) return; } - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { if (const Mesh *mesh = geometry_set.get_mesh()) { geometry_set.replace_mesh(mesh_subsurf_calc( mesh, level, vert_crease, edge_crease, boundary_smooth, uv_smooth, use_limit_surface)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_tool_set_face_set.cc b/source/blender/nodes/geometry/nodes/node_geo_tool_set_face_set.cc index 41125508c6d..6824a928b41 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_tool_set_face_set.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_tool_set_face_set.cc @@ -4,6 +4,8 @@ #include "DNA_mesh_types.h" +#include "GEO_foreach_geometry.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_tool_set_face_set_cc { @@ -37,7 +39,7 @@ static void node_geo_exec(GeoNodeExecParams params) const bool is_zero = is_constant_zero(face_set); GeometrySet geometry = params.extract_input("Mesh"); - geometry.modify_geometry_sets([&](GeometrySet &geometry) { + geometry::foreach_real_geometry(geometry, [&](GeometrySet &geometry) { if (Mesh *mesh = geometry.get_mesh_for_write()) { if (is_zero) { mesh->attributes_for_write().remove(".sculpt_face_set"); diff --git a/source/blender/nodes/geometry/nodes/node_geo_tool_set_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_tool_set_selection.cc index a1db004d33f..4c2fa1f8d14 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_tool_set_selection.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_tool_set_selection.cc @@ -12,6 +12,8 @@ #include "RNA_enum_types.hh" +#include "GEO_foreach_geometry.hh" + #include "FN_multi_function_builder.hh" #include "node_geometry_util.hh" @@ -95,7 +97,7 @@ static void node_geo_exec(GeoNodeExecParams params) const GField selection = params.extract_input("Selection"); const AttrDomain domain = AttrDomain(params.node().custom1); const bke::DataTypeConversions &conversions = bke::get_implicit_type_conversions(); - geometry.modify_geometry_sets([&](GeometrySet &geometry) { + geometry::foreach_real_geometry(geometry, [&](GeometrySet &geometry) { if (Mesh *mesh = geometry.get_mesh_for_write()) { switch (mode) { case OB_MODE_EDIT: { diff --git a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc index 8dd80a9e57d..d4b323a12b5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc @@ -4,8 +4,8 @@ #include "DNA_mesh_types.h" +#include "GEO_foreach_geometry.hh" #include "GEO_mesh_triangulate.hh" - #include "GEO_randomize.hh" #include "node_geometry_util.hh" @@ -85,7 +85,7 @@ static void node_geo_exec(GeoNodeExecParams params) const auto ngon_method = params.extract_input("N-gon Method"); const auto quad_method = params.extract_input("Quad Method"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { const Mesh *src_mesh = geometry_set.get_mesh(); if (!src_mesh) { return; diff --git a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc index dbb5cb1fd73..ae26052d142 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc @@ -15,6 +15,7 @@ #include "BKE_volume_grid.hh" #include "BKE_volume_to_mesh.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_randomize.hh" namespace blender::nodes::node_geo_volume_to_mesh_cc { @@ -191,10 +192,10 @@ static void node_geo_exec(GeoNodeExecParams params) { #ifdef WITH_OPENVDB GeometrySet geometry_set = params.extract_input("Volume"); - geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) { Mesh *mesh = create_mesh_from_volume(geometry_set, params); geometry_set.replace_mesh(mesh); - geometry_set.keep_only_during_modify({GeometryComponent::Type::Mesh}); + geometry_set.keep_only({GeometryComponent::Type::Mesh, GeometryComponent::Type::Edit}); }); params.set_output("Mesh", std::move(geometry_set)); #else diff --git a/source/blender/nodes/intern/geometry_nodes_execute.cc b/source/blender/nodes/intern/geometry_nodes_execute.cc index 2f4fd4f2985..4e0aeb622e3 100644 --- a/source/blender/nodes/intern/geometry_nodes_execute.cc +++ b/source/blender/nodes/intern/geometry_nodes_execute.cc @@ -16,6 +16,8 @@ #include "NOD_node_declaration.hh" #include "NOD_socket.hh" +#include "GEO_foreach_geometry.hh" + #include "BKE_geometry_fields.hh" #include "BKE_geometry_nodes_reference_set.hh" #include "BKE_geometry_set.hh" @@ -738,20 +740,13 @@ static MultiValueMap find_output_attribute static Vector compute_attributes_to_store( const bke::GeometrySet &geometry, const MultiValueMap &outputs_by_domain, - const bool do_instances) + const Span component_types) { Vector attributes_to_store; - for (const auto component_type : {bke::GeometryComponent::Type::Mesh, - bke::GeometryComponent::Type::PointCloud, - bke::GeometryComponent::Type::Curve, - bke::GeometryComponent::Type::Instance}) - { + for (const auto component_type : component_types) { if (!geometry.has(component_type)) { continue; } - if (!do_instances && component_type == bke::GeometryComponent::Type::Instance) { - continue; - } const bke::GeometryComponent &component = *geometry.get_component(component_type); const bke::AttributeAccessor attributes = *component.attributes(); for (const auto item : outputs_by_domain.items()) { @@ -838,24 +833,32 @@ static void store_output_attributes(bke::GeometrySet &geometry, if (outputs_by_domain.size() == 0) { return; } + + { + /* Handle top level instances separately first. */ + Vector attributes_to_store = compute_attributes_to_store( + geometry, outputs_by_domain, {bke::GeometryComponent::Type::Instance}); + store_computed_output_attributes(geometry, attributes_to_store); + } + const bool only_instance_attributes = outputs_by_domain.size() == 1 && *outputs_by_domain.keys().begin() == bke::AttrDomain::Instance; if (only_instance_attributes) { - /* No need to call #modify_geometry_sets when only adding attributes to top-level instances. + /* No need to call #foreach_real_geometry when only adding attributes to top-level instances. * This avoids some unnecessary data copies currently if some sub-geometries are not yet owned * by the geometry set, i.e. they use #GeometryOwnershipType::Editable/ReadOnly. */ - Vector attributes_to_store = compute_attributes_to_store( - geometry, outputs_by_domain, true); - store_computed_output_attributes(geometry, attributes_to_store); return; } - geometry.modify_geometry_sets([&](bke::GeometrySet &instance_geometry) { + geometry::foreach_real_geometry(geometry, [&](bke::GeometrySet &instance_geometry) { /* Instance attributes should only be created for the top-level geometry. */ - const bool do_instances = &geometry == &instance_geometry; Vector attributes_to_store = compute_attributes_to_store( - instance_geometry, outputs_by_domain, do_instances); + instance_geometry, + outputs_by_domain, + {bke::GeometryComponent::Type::Mesh, + bke::GeometryComponent::Type::PointCloud, + bke::GeometryComponent::Type::Curve}); store_computed_output_attributes(instance_geometry, attributes_to_store); }); } diff --git a/source/blender/nodes/intern/geometry_nodes_foreach_geometry_element_zone.cc b/source/blender/nodes/intern/geometry_nodes_foreach_geometry_element_zone.cc index c8d5e42055b..d6a381ba01d 100644 --- a/source/blender/nodes/intern/geometry_nodes_foreach_geometry_element_zone.cc +++ b/source/blender/nodes/intern/geometry_nodes_foreach_geometry_element_zone.cc @@ -13,6 +13,7 @@ #include "BKE_node_socket_value.hh" #include "GEO_extract_elements.hh" +#include "GEO_foreach_geometry.hh" #include "GEO_join_geometries.hh" #include "FN_lazy_function_graph_executor.hh" @@ -1137,7 +1138,7 @@ void LazyFunctionForReduceForeachGeometryElement::handle_generation_items_group( } } else { - geometry.modify_geometry_sets([&](GeometrySet &sub_geometry) { + geometry::foreach_real_geometry(geometry, [&](GeometrySet &sub_geometry) { for (const GeometryComponent::Type component_type : {GeometryComponent::Type::Mesh, GeometryComponent::Type::PointCloud, diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc index cfed417a100..1ada3f89263 100644 --- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc +++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc @@ -54,6 +54,8 @@ #include "DEG_depsgraph_query.hh" +#include "GEO_foreach_geometry.hh" + #include "list_function_eval.hh" #include "volume_grid_function_eval.hh" @@ -909,7 +911,7 @@ class LazyFunctionForViewerNode : public LazyFunction { } } else { - geometry.modify_geometry_sets([&](GeometrySet &geometry) { + geometry::foreach_real_geometry(geometry, [&](GeometrySet &geometry) { for (const bke::GeometryComponent::Type type : {bke::GeometryComponent::Type::Mesh, bke::GeometryComponent::Type::PointCloud, diff --git a/tests/files/modeling/geometry_nodes/instance/instance_on_points_in_instances.blend b/tests/files/modeling/geometry_nodes/instance/instance_on_points_in_instances.blend new file mode 100644 index 00000000000..d863bf838e1 --- /dev/null +++ b/tests/files/modeling/geometry_nodes/instance/instance_on_points_in_instances.blend @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cb6c15a1d39ed18a477e93123ac886226ac8473b95821aa4647547136b61eacd +size 564009