From 89c7c115cebb2ac0aaaeb98eb95decc7b5a129c8 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 14 Oct 2021 12:43:36 -0500 Subject: Geometry Nodes: Create empty components less often Avoiding creating empty components can be a hassle for code that interacts with a geometry set. One easy way to do that was calling the functions that retrieved mutable access to geometry data directly, like get_mesh_for_write. This commit makes it so that sort of direct function does not create an empty component if there is no data. Another way to create an empty component was calling the replace_* methods with a null pointer. It's more convenient to have a nice API that handles those cases without creating an empty component. It's still convenient that the regular get_component_for_write adds the component if it doesn't exist, because that's often a nice way to add data to the geometry set. Differential Revision: https://developer.blender.org/D12862 --- source/blender/blenkernel/BKE_geometry_set.hh | 9 +++ source/blender/blenkernel/intern/geometry_set.cc | 80 +++++++++++++++++------- 2 files changed, 67 insertions(+), 22 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index b36d15578a7..66466e3972e 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -357,6 +357,15 @@ struct GeometrySet { GeometryOwnershipType ownership = GeometryOwnershipType::Owned); void replace_curve(CurveEval *curve, GeometryOwnershipType ownership = GeometryOwnershipType::Owned); + + private: + /* Utility to retrieve a mutable component without creating it. */ + GeometryComponent *get_component_ptr(GeometryComponentType type); + template Component *get_component_ptr() + { + BLI_STATIC_ASSERT(is_geometry_component_v, ""); + return static_cast(get_component_ptr(Component::static_type)); + } }; /** A geometry component that can store a mesh. */ diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc index 84daa06554a..33ead37979d 100644 --- a/source/blender/blenkernel/intern/geometry_set.cc +++ b/source/blender/blenkernel/intern/geometry_set.cc @@ -139,6 +139,16 @@ GeometryComponent &GeometrySet::get_component_for_write(GeometryComponentType co }); } +/** + * Retrieve the pointer to a component without creating it if it does not exist, + * unlike #get_component_for_write. + */ +GeometryComponent *GeometrySet::get_component_ptr(GeometryComponentType type) +{ + GeometryComponentPtr *component_ptr = components_.lookup_ptr(type); + return component_ptr == nullptr ? nullptr : component_ptr->get(); +} + /* Get the component of the given type. Might return null if the component does not exist yet. */ const GeometryComponent *GeometrySet::get_component_for_read( GeometryComponentType component_type) const @@ -340,8 +350,10 @@ bool GeometrySet::is_empty() const GeometrySet GeometrySet::create_with_mesh(Mesh *mesh, GeometryOwnershipType ownership) { GeometrySet geometry_set; - MeshComponent &component = geometry_set.get_component_for_write(); - component.replace(mesh, ownership); + if (mesh != nullptr) { + MeshComponent &component = geometry_set.get_component_for_write(); + component.replace(mesh, ownership); + } return geometry_set; } @@ -350,8 +362,10 @@ GeometrySet GeometrySet::create_with_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership) { GeometrySet geometry_set; - PointCloudComponent &component = geometry_set.get_component_for_write(); - component.replace(pointcloud, ownership); + if (pointcloud != nullptr) { + PointCloudComponent &component = geometry_set.get_component_for_write(); + component.replace(pointcloud, ownership); + } return geometry_set; } @@ -359,65 +373,87 @@ GeometrySet GeometrySet::create_with_pointcloud(PointCloud *pointcloud, GeometrySet GeometrySet::create_with_curve(CurveEval *curve, GeometryOwnershipType ownership) { GeometrySet geometry_set; - CurveComponent &component = geometry_set.get_component_for_write(); - component.replace(curve, ownership); + if (curve != nullptr) { + CurveComponent &component = geometry_set.get_component_for_write(); + component.replace(curve, ownership); + } return geometry_set; } /* Clear the existing mesh and replace it with the given one. */ void GeometrySet::replace_mesh(Mesh *mesh, GeometryOwnershipType ownership) { - MeshComponent &component = this->get_component_for_write(); - component.replace(mesh, ownership); + if (mesh == nullptr) { + this->remove(); + } + else { + MeshComponent &component = this->get_component_for_write(); + component.replace(mesh, ownership); + } } /* Clear the existing curve and replace it with the given one. */ void GeometrySet::replace_curve(CurveEval *curve, GeometryOwnershipType ownership) { - CurveComponent &component = this->get_component_for_write(); - component.replace(curve, ownership); + if (curve == nullptr) { + this->remove(); + } + else { + CurveComponent &component = this->get_component_for_write(); + component.replace(curve, ownership); + } } /* Clear the existing point cloud and replace with the given one. */ void GeometrySet::replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership) { - PointCloudComponent &pointcloud_component = this->get_component_for_write(); - pointcloud_component.replace(pointcloud, ownership); + if (pointcloud == nullptr) { + this->remove(); + } + else { + PointCloudComponent &component = this->get_component_for_write(); + component.replace(pointcloud, ownership); + } } /* Clear the existing volume and replace with the given one. */ void GeometrySet::replace_volume(Volume *volume, GeometryOwnershipType ownership) { - VolumeComponent &volume_component = this->get_component_for_write(); - volume_component.replace(volume, ownership); + if (volume == nullptr) { + this->remove(); + } + else { + VolumeComponent &component = this->get_component_for_write(); + component.replace(volume, ownership); + } } /* Returns a mutable mesh or null. No ownership is transferred. */ Mesh *GeometrySet::get_mesh_for_write() { - MeshComponent &component = this->get_component_for_write(); - return component.get_for_write(); + MeshComponent *component = this->get_component_ptr(); + return component == nullptr ? nullptr : component->get_for_write(); } /* Returns a mutable point cloud or null. No ownership is transferred. */ PointCloud *GeometrySet::get_pointcloud_for_write() { - PointCloudComponent &component = this->get_component_for_write(); - return component.get_for_write(); + PointCloudComponent *component = this->get_component_ptr(); + return component == nullptr ? nullptr : component->get_for_write(); } /* Returns a mutable volume or null. No ownership is transferred. */ Volume *GeometrySet::get_volume_for_write() { - VolumeComponent &component = this->get_component_for_write(); - return component.get_for_write(); + VolumeComponent *component = this->get_component_ptr(); + return component == nullptr ? nullptr : component->get_for_write(); } /* Returns a mutable curve or null. No ownership is transferred. */ CurveEval *GeometrySet::get_curve_for_write() { - CurveComponent &component = this->get_component_for_write(); - return component.get_for_write(); + CurveComponent *component = this->get_component_ptr(); + return component == nullptr ? nullptr : component->get_for_write(); } void GeometrySet::attribute_foreach(const Span component_types, -- cgit v1.2.3