Blender V4.3
geometry_set.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_bounds.hh"
6#include "BLI_map.hh"
8#include "BLI_task.hh"
9
10#include "BLT_translation.hh"
11
12#include "BKE_attribute.hh"
13#include "BKE_curves.hh"
14#include "BKE_geometry_set.hh"
16#include "BKE_grease_pencil.hh"
17#include "BKE_instances.hh"
18#include "BKE_lib_id.hh"
19#include "BKE_mesh.hh"
20#include "BKE_mesh_wrapper.hh"
21#include "BKE_modifier.hh"
22#include "BKE_object_types.hh"
23#include "BKE_pointcloud.hh"
24#include "BKE_volume.hh"
25
27#include "DNA_object_types.h"
29
30#include "BLI_rand.hh"
31
32#include "MEM_guardedalloc.h"
33
34namespace blender::bke {
35
36/* -------------------------------------------------------------------- */
41
43{
44 switch (component_type) {
45 case Type::Mesh:
49 case Type::Instance:
51 case Type::Volume:
53 case Type::Curve:
55 case Type::Edit:
59 }
61 return {};
62}
63
65{
66 if (this->is_empty()) {
67 return 0;
68 }
69 const std::optional<AttributeAccessor> attributes = this->attributes();
70 if (attributes.has_value()) {
71 return attributes->domain_size(domain);
72 }
73 return 0;
74}
75
76std::optional<AttributeAccessor> GeometryComponent::attributes() const
77{
78 return std::nullopt;
79};
80std::optional<MutableAttributeAccessor> GeometryComponent::attributes_for_write()
81{
82 return std::nullopt;
83}
84
86
88{
89 return type_;
90}
91
93{
94 return false;
95}
96
97void GeometryComponent::delete_self()
98{
99 delete this;
100}
101
102void GeometryComponent::delete_data_only()
103{
104 this->clear();
105}
106
109/* -------------------------------------------------------------------- */
113GeometrySet::GeometrySet() = default;
114GeometrySet::GeometrySet(const GeometrySet &other) = default;
115GeometrySet::GeometrySet(GeometrySet &&other) = default;
116GeometrySet::~GeometrySet() = default;
117GeometrySet &GeometrySet::operator=(const GeometrySet &other) = default;
118GeometrySet &GeometrySet::operator=(GeometrySet &&other) = default;
119
121{
122 GeometryComponentPtr &component_ptr = components_[size_t(component_type)];
123 if (!component_ptr) {
124 /* If the component did not exist before, create a new one. */
125 component_ptr = GeometryComponent::create(component_type);
126 }
127 else if (component_ptr->is_mutable()) {
128 /* If the referenced component is already mutable, return it directly. */
129 component_ptr->tag_ensured_mutable();
130 }
131 else {
132 /* If the referenced component is shared, make a copy. The copy is not shared and is
133 * therefore mutable. */
134 component_ptr = component_ptr->copy();
135 }
136 return const_cast<GeometryComponent &>(*component_ptr);
137}
138
139GeometryComponent *GeometrySet::get_component_ptr(GeometryComponent::Type type)
140{
141 if (this->has(type)) {
142 return &this->get_component_for_write(type);
143 }
144 return nullptr;
145}
146
148{
149 return components_[size_t(component_type)].get();
150}
151
152bool GeometrySet::has(const GeometryComponent::Type component_type) const
153{
154 const GeometryComponentPtr &component = components_[size_t(component_type)];
155 return component.has_value() && !component->is_empty();
156}
157
159{
160 components_[size_t(component_type)].reset();
161}
162
164{
165 for (GeometryComponentPtr &component_ptr : components_) {
166 if (component_ptr) {
167 if (!component_types.contains(component_ptr->type())) {
168 component_ptr.reset();
169 }
170 }
171 }
172}
173
175{
176 Vector<GeometryComponent::Type> extended_types = component_types;
179 this->keep_only(extended_types);
180}
181
186
188{
189 BLI_assert(!components_[size_t(component.type())]);
190 component.add_user();
191 components_[size_t(component.type())] = GeometryComponentPtr(
192 const_cast<GeometryComponent *>(&component));
193}
194
196{
198 for (const GeometryComponentPtr &component_ptr : components_) {
199 if (component_ptr) {
200 components.append(component_ptr.get());
201 }
202 }
203 return components;
204}
205
206std::optional<Bounds<float3>> GeometrySet::compute_boundbox_without_instances() const
207{
208 std::optional<Bounds<float3>> bounds;
209 if (const PointCloud *pointcloud = this->get_pointcloud()) {
210 bounds = bounds::merge(bounds, pointcloud->bounds_min_max());
211 }
212 if (const Mesh *mesh = this->get_mesh()) {
213 bounds = bounds::merge(bounds, mesh->bounds_min_max());
214 }
215 if (const Volume *volume = this->get_volume()) {
216 bounds = bounds::merge(bounds, BKE_volume_min_max(volume));
217 }
218 if (const Curves *curves_id = this->get_curves()) {
219 bounds = bounds::merge(bounds, curves_id->geometry.wrap().bounds_min_max());
220 }
221 if (const GreasePencil *grease_pencil = this->get_grease_pencil()) {
222 bounds = bounds::merge(bounds, grease_pencil->bounds_min_max_eval());
223 }
224 return bounds;
225}
226
227std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set)
228{
230 if (const Mesh *mesh = geometry_set.get_mesh()) {
231 parts.append(std::to_string(mesh->verts_num) + " verts");
232 parts.append(std::to_string(mesh->edges_num) + " edges");
233 parts.append(std::to_string(mesh->faces_num) + " faces");
234 parts.append(std::to_string(mesh->corners_num) + " corners");
235 }
236 if (const Curves *curves = geometry_set.get_curves()) {
237 parts.append(std::to_string(curves->geometry.point_num) + " control points");
238 parts.append(std::to_string(curves->geometry.curve_num) + " curves");
239 }
240 if (const GreasePencil *grease_pencil = geometry_set.get_grease_pencil()) {
241 parts.append(std::to_string(grease_pencil->layers().size()) + " grease pencil layers");
242 }
243 if (const PointCloud *point_cloud = geometry_set.get_pointcloud()) {
244 parts.append(std::to_string(point_cloud->totpoint) + " points");
245 }
246 if (const Volume *volume = geometry_set.get_volume()) {
247 parts.append(std::to_string(BKE_volume_num_grids(volume)) + " volume grids");
248 }
249 if (geometry_set.has_instances()) {
250 parts.append(std::to_string(geometry_set.get_instances()->instances_num()) + " instances");
251 }
252 if (geometry_set.get_curve_edit_hints()) {
253 parts.append("curve edit hints");
254 }
255
256 stream << "<GeometrySet: ";
257 for (const int i : parts.index_range()) {
258 stream << parts[i];
259 if (i < parts.size() - 1) {
260 stream << ", ";
261 }
262 }
263 stream << ">";
264 return stream;
265}
266
268{
269 for (GeometryComponentPtr &component_ptr : components_) {
270 component_ptr.reset();
271 }
272}
273
275{
276 for (GeometryComponentPtr &component_ptr : components_) {
277 if (!component_ptr) {
278 continue;
279 }
280 if (component_ptr->owns_direct_data()) {
281 continue;
282 }
283 GeometryComponent &component_for_write = this->get_component_for_write(component_ptr->type());
284 component_for_write.ensure_owns_direct_data();
285 }
286}
287
289{
290 if (Instances *instances = this->get_instances_for_write()) {
291 instances->ensure_geometry_instances();
292 }
294}
295
297{
298 for (const GeometryComponentPtr &component_ptr : components_) {
299 if (component_ptr) {
300 if (!component_ptr->owns_direct_data()) {
301 return false;
302 }
303 }
304 }
305 return true;
306}
307
309{
310 const MeshComponent *component = this->get_component<MeshComponent>();
311 return (component == nullptr) ? nullptr : component->get();
312}
313
315{
316 const MeshComponent *component = this->get_component<MeshComponent>();
317 return component != nullptr && component->has_mesh();
318}
319
321{
323 return (component == nullptr) ? nullptr : component->get();
324}
325
327{
328 const VolumeComponent *component = this->get_component<VolumeComponent>();
329 return (component == nullptr) ? nullptr : component->get();
330}
331
333{
334 const CurveComponent *component = this->get_component<CurveComponent>();
335 return (component == nullptr) ? nullptr : component->get();
336}
337
339{
340 const InstancesComponent *component = this->get_component<InstancesComponent>();
341 return (component == nullptr) ? nullptr : component->get();
342}
343
345{
347 return (component == nullptr) ? nullptr : component->curves_edit_hints_.get();
348}
349
351{
353 return (component == nullptr) ? nullptr : component->gizmo_edit_hints_.get();
354}
355
357{
359 return (component == nullptr) ? nullptr : component->get();
360}
361
363{
365 return component != nullptr && component->has_pointcloud();
366}
367
369{
370 const InstancesComponent *component = this->get_component<InstancesComponent>();
371 return component != nullptr && component->get() != nullptr &&
372 component->get()->instances_num() >= 1;
373}
374
376{
377 const VolumeComponent *component = this->get_component<VolumeComponent>();
378 return component != nullptr && component->has_volume();
379}
380
382{
383 const CurveComponent *component = this->get_component<CurveComponent>();
384 return component != nullptr && component->has_curves();
385}
386
388{
389 for (const GeometryComponentPtr &component_ptr : components_) {
390 if (component_ptr) {
391 if (component_ptr->type() != GeometryComponent::Type::Instance) {
392 return true;
393 }
394 }
395 }
396 return false;
397}
398
400{
402 return component != nullptr && component->has_grease_pencil();
403}
404
406{
407 return !(this->has_mesh() || this->has_curves() || this->has_pointcloud() ||
408 this->has_volume() || this->has_instances() || this->has_grease_pencil());
409}
410
412{
413 GeometrySet geometry_set;
414 geometry_set.replace_mesh(mesh, ownership);
415 return geometry_set;
416}
417
419{
420 GeometrySet geometry_set;
421 geometry_set.replace_volume(volume, ownership);
422 return geometry_set;
423}
424
426{
427 GeometrySet geometry_set;
428 geometry_set.replace_pointcloud(pointcloud, ownership);
429 return geometry_set;
430}
431
433{
434 GeometrySet geometry_set;
435 geometry_set.replace_curves(curves, ownership);
436 return geometry_set;
437}
438
440{
441 GeometrySet geometry_set;
442 geometry_set.replace_instances(instances, ownership);
443 return geometry_set;
444}
445
447 GeometryOwnershipType ownership)
448{
449 GeometrySet geometry_set;
450 geometry_set.replace_grease_pencil(grease_pencil, ownership);
451 return geometry_set;
452}
453
455{
456 if (mesh == nullptr) {
457 this->remove<MeshComponent>();
458 return;
459 }
460 if (mesh == this->get_mesh()) {
461 return;
462 }
463 this->remove<MeshComponent>();
465 component.replace(mesh, ownership);
466}
467
469{
470 if (curves == nullptr) {
472 return;
473 }
474 if (curves == this->get_curves()) {
475 return;
476 }
479 component.replace(curves, ownership);
480}
481
483{
484 if (instances == nullptr) {
486 return;
487 }
488 if (instances == this->get_instances()) {
489 return;
490 }
493 component.replace(instances, ownership);
494}
495
497{
498 if (pointcloud == nullptr) {
500 return;
501 }
502 if (pointcloud == this->get_pointcloud()) {
503 return;
504 }
507 component.replace(pointcloud, ownership);
508}
509
511{
512 if (volume == nullptr) {
514 return;
515 }
516 if (volume == this->get_volume()) {
517 return;
518 }
521 component.replace(volume, ownership);
522}
523
525 GeometryOwnershipType ownership)
526{
527 if (grease_pencil == nullptr) {
529 return;
530 }
531 if (grease_pencil == this->get_grease_pencil()) {
532 return;
533 }
536 component.replace(grease_pencil, ownership);
537}
538
540{
541 MeshComponent *component = this->get_component_ptr<MeshComponent>();
542 return component == nullptr ? nullptr : component->get_for_write();
543}
544
546{
547 PointCloudComponent *component = this->get_component_ptr<PointCloudComponent>();
548 return component == nullptr ? nullptr : component->get_for_write();
549}
550
552{
553 VolumeComponent *component = this->get_component_ptr<VolumeComponent>();
554 return component == nullptr ? nullptr : component->get_for_write();
555}
556
558{
559 CurveComponent *component = this->get_component_ptr<CurveComponent>();
560 return component == nullptr ? nullptr : component->get_for_write();
561}
562
564{
565 InstancesComponent *component = this->get_component_ptr<InstancesComponent>();
566 return component == nullptr ? nullptr : component->get_for_write();
567}
568
578
580{
581 if (!this->has<GeometryComponentEditData>()) {
582 return nullptr;
583 }
584 GeometryComponentEditData &component =
586 return component.gizmo_edit_hints_.get();
587}
588
590{
591 GreasePencilComponent *component = this->get_component_ptr<GreasePencilComponent>();
592 return component == nullptr ? nullptr : component->get_for_write();
593}
594
596{
597 for (const GeometryComponentPtr &component : components_) {
598 if (component) {
599 memory.add_shared(component.get(), [&](MemoryCounter &shared_memory) {
600 component->count_memory(shared_memory);
601 });
602 }
603 }
604}
605
607 const bool include_instances,
609{
610 for (const GeometryComponent::Type component_type : component_types) {
611 if (!this->has(component_type)) {
612 continue;
613 }
614 const GeometryComponent &component = *this->get_component(component_type);
615 const std::optional<AttributeAccessor> attributes = component.attributes();
616 if (attributes.has_value()) {
617 attributes->foreach_attribute([&](const AttributeIter &iter) {
618 callback(iter.name, {iter.domain, iter.data_type}, component);
619 });
620 }
621 }
622 if (include_instances && this->has_instances()) {
623 const Instances &instances = *this->get_instances();
624 instances.foreach_referenced_geometry([&](const GeometrySet &instance_geometry_set) {
625 instance_geometry_set.attribute_foreach(component_types, include_instances, callback);
626 });
627 }
628}
629
631 const AttributeAccessor src_attributes,
632 MutableAttributeAccessor dst_attributes,
633 const AttributeFilter &attribute_filter)
634{
635 src_attributes.foreach_attribute([&](const AttributeIter &iter) {
636 if (attribute_filter.allow_skip(iter.name)) {
637 return;
638 }
639 const GAttributeReader src = iter.get(AttrDomain::Layer);
640 if (src.sharing_info && src.varray.is_span()) {
641 const AttributeInitShared init(src.varray.get_internal_span().data(), *src.sharing_info);
642 if (dst_attributes.add(iter.name, AttrDomain::Instance, iter.data_type, init)) {
643 return;
644 }
645 }
648 if (!dst) {
649 return;
650 }
651 array_utils::copy(src.varray, dst.span);
652 dst.finish();
653 });
654}
655
657 const StringRef name)
658{
659 switch (type) {
661 static auto component = GeometryComponent::create(type);
662 return component->attributes()->is_builtin(name);
663 }
665 static auto component = GeometryComponent::create(type);
666 return component->attributes()->is_builtin(name);
667 }
669 static auto component = GeometryComponent::create(type);
670 return component->attributes()->is_builtin(name);
671 }
673 static auto component = GeometryComponent::create(type);
674 return component->attributes()->is_builtin(name);
675 }
677 static auto grease_pencil_component = GeometryComponent::create(
679 static auto curves_component = GeometryComponent::create(GeometryComponent::Type::Curve);
680 return grease_pencil_component->attributes()->is_builtin(name) ||
681 curves_component->attributes()->is_builtin(name);
682 }
685 return false;
686 }
687 }
689 return false;
690}
691
693 const Span<GeometryComponent::Type> component_types,
694 const GeometryComponent::Type dst_component_type,
695 bool include_instances,
696 const AttributeFilter &attribute_filter,
697 Map<StringRef, AttributeKind> &r_attributes) const
698{
699 this->attribute_foreach(
700 component_types,
701 include_instances,
702 [&](const StringRef attribute_id,
703 const AttributeMetaData &meta_data,
704 const GeometryComponent &component) {
705 if (component.attributes()->is_builtin(attribute_id)) {
706 if (!attribute_is_builtin_on_component_type(dst_component_type, attribute_id)) {
707 /* Don't propagate built-in attributes that are not built-in on the destination
708 * component. */
709 return;
710 }
711 }
712 if (meta_data.data_type == CD_PROP_STRING) {
713 /* Propagating string attributes is not supported yet. */
714 return;
715 }
716 if (attribute_filter.allow_skip(attribute_id)) {
717 return;
718 }
719
720 AttrDomain domain = meta_data.domain;
721 if (dst_component_type != GeometryComponent::Type::Instance &&
722 domain == AttrDomain::Instance) {
723 domain = AttrDomain::Point;
724 }
725
726 auto add_info = [&](AttributeKind *attribute_kind) {
727 attribute_kind->domain = domain;
728 attribute_kind->data_type = meta_data.data_type;
729 };
730 auto modify_info = [&](AttributeKind *attribute_kind) {
731 attribute_kind->domain = bke::attribute_domain_highest_priority(
732 {attribute_kind->domain, domain});
733 attribute_kind->data_type = bke::attribute_data_type_highest_complexity(
734 {attribute_kind->data_type, meta_data.data_type});
735 };
736 r_attributes.add_or_modify(attribute_id, add_info, modify_info);
737 });
738}
739
740static void gather_component_types_recursive(const GeometrySet &geometry_set,
741 const bool include_instances,
742 const bool ignore_empty,
744{
745 for (const GeometryComponent *component : geometry_set.get_components()) {
746 if (ignore_empty) {
747 if (component->is_empty()) {
748 continue;
749 }
750 }
751 r_types.append_non_duplicates(component->type());
752 }
753 if (!include_instances) {
754 return;
755 }
756 const Instances *instances = geometry_set.get_instances();
757 if (instances == nullptr) {
758 return;
759 }
760 instances->foreach_referenced_geometry([&](const GeometrySet &instance_geometry_set) {
762 instance_geometry_set, include_instances, ignore_empty, r_types);
763 });
764}
765
766Vector<GeometryComponent::Type> GeometrySet::gather_component_types(const bool include_instances,
767 bool ignore_empty) const
768{
770 gather_component_types_recursive(*this, include_instances, ignore_empty, types);
771 return types;
772}
773
775 Vector<GeometrySet *> &r_geometry_sets)
776{
777 r_geometry_sets.append(&geometry_set);
778 if (!geometry_set.has_instances()) {
779 return;
780 }
781 /* In the future this can be improved by deduplicating instance references across different
782 * instances. */
783 Instances &instances = *geometry_set.get_instances_for_write();
784 instances.ensure_geometry_instances();
785 for (const int handle : instances.references().index_range()) {
786 if (instances.references()[handle].type() == InstanceReference::Type::GeometrySet) {
787 GeometrySet &instance_geometry = instances.geometry_set_from_reference(handle);
788 gather_mutable_geometry_sets(instance_geometry, r_geometry_sets);
789 }
790 }
791}
792
793void GeometrySet::modify_geometry_sets(ForeachSubGeometryCallback callback)
794{
795 Vector<GeometrySet *> geometry_sets;
796 gather_mutable_geometry_sets(*this, geometry_sets);
797 if (geometry_sets.size() == 1) {
798 /* Avoid possible overhead and a large call stack when multithreading is pointless. */
799 callback(*geometry_sets.first());
800 }
801 else {
802 threading::parallel_for_each(geometry_sets,
803 [&](GeometrySet *geometry_set) { callback(*geometry_set); });
804 }
805}
806
808{
809 const GeometrySet *geometry_set = object.runtime->geometry_set_eval;
810 if (geometry_set == nullptr) {
811 return false;
812 }
813 if (geometry_set->has_component<InstancesComponent>()) {
814 return true;
815 }
816 if (object.type != OB_MESH && geometry_set->has_component<MeshComponent>()) {
817 return true;
818 }
819 if (object.type != OB_POINTCLOUD && geometry_set->has_component<PointCloudComponent>()) {
820 return true;
821 }
822 if (object.type != OB_VOLUME && geometry_set->has_component<VolumeComponent>()) {
823 return true;
824 }
825 if (!ELEM(object.type, OB_CURVES_LEGACY, OB_FONT) &&
826 geometry_set->has_component<CurveComponent>())
827 {
828 return true;
829 }
830 if (object.type != OB_GREASE_PENCIL && geometry_set->has_component<GreasePencilComponent>()) {
831 return true;
832 }
833 return false;
834}
835
838} // namespace blender::bke
Low-level operations for curves.
Low-level operations for grease pencil.
General operations for point clouds.
Volume data-block.
int BKE_volume_num_grids(const Volume *volume)
std::optional< blender::Bounds< blender::float3 > > BKE_volume_min_max(const Volume *volume)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define ELEM(...)
Object groups, one object can be in many groups at once.
@ CD_PROP_STRING
Object is a sort of wrapper for general info.
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
Read Guarded memory(de)allocation.
void init()
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
Definition BLI_map.hh:457
constexpr bool contains(const T &value) const
Definition BLI_span.hh:278
int64_t size() const
void append(const T &value)
void append_non_duplicates(const T &value)
const T & first() const
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
GAttributeReader get() const
void replace(Curves *curve, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
std::unique_ptr< GizmoEditHints > gizmo_edit_hints_
std::unique_ptr< CurvesEditHints > curves_edit_hints_
int attribute_domain_size(AttrDomain domain) const
virtual std::optional< AttributeAccessor > attributes() const
virtual std::optional< MutableAttributeAccessor > attributes_for_write()
virtual bool is_empty() const
virtual void count_memory(MemoryCounter &memory) const
virtual void ensure_owns_direct_data()=0
static GeometryComponentPtr create(Type component_type)
void replace(GreasePencil *grease_pencil, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void replace(Instances *instances, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void foreach_referenced_geometry(FunctionRef< void(const GeometrySet &geometry_set)> callback) const
int instances_num() const
Definition instances.cc:390
void replace(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
void replace(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void replace(Volume *volume, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void add_shared(const ImplicitSharingInfo *sharing_info, const FunctionRef< void(MemoryCounter &shared_memory)> count_fn)
DEGForeachIDComponentCallback callback
static char ** types
Definition makesdna.cc:71
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
ImplicitSharingPtr< GeometryComponent > GeometryComponentPtr
static void gather_component_types_recursive(const GeometrySet &geometry_set, const bool include_instances, const bool ignore_empty, Vector< GeometryComponent::Type > &r_types)
static void gather_mutable_geometry_sets(GeometrySet &geometry_set, Vector< GeometrySet * > &r_geometry_sets)
bool attribute_is_builtin_on_component_type(const GeometryComponent::Type type, StringRef name)
eCustomDataType attribute_data_type_highest_complexity(Span< eCustomDataType > data_types)
AttrDomain attribute_domain_highest_priority(Span< AttrDomain > domains)
std::ostream & operator<<(std::ostream &stream, const GeometrySet &geometry_set)
bool object_has_geometry_set_instances(const Object &object)
Bounds< T > merge(const Bounds< T > &a, const Bounds< T > &b)
Definition BLI_bounds.hh:24
void parallel_for_each(Range &&range, const Function &function)
Definition BLI_task.hh:58
bool allow_skip(const StringRef name) const
void replace_volume(Volume *volume, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void keep_only(Span< GeometryComponent::Type > component_types)
const CurvesEditHints * get_curve_edit_hints() const
GeometrySet & operator=(const GeometrySet &other)
static GeometrySet from_instances(Instances *instances, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
static GeometrySet from_grease_pencil(GreasePencil *grease_pencil, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
PointCloud * get_pointcloud_for_write()
static GeometrySet from_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
GizmoEditHints * get_gizmo_edit_hints_for_write()
void replace_instances(Instances *instances, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Instances * get_instances_for_write()
const GreasePencil * get_grease_pencil() const
const Component * get_component() const
const GizmoEditHints * get_gizmo_edit_hints() const
Vector< const GeometryComponent * > get_components() const
const Volume * get_volume() const
static GeometrySet from_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void gather_attributes_for_propagation(Span< GeometryComponent::Type > component_types, GeometryComponent::Type dst_component_type, bool include_instances, const AttributeFilter &attribute_filter, Map< StringRef, AttributeKind > &r_attributes) const
void replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void keep_only_during_modify(Span< GeometryComponent::Type > component_types)
const Curves * get_curves() const
static GeometrySet from_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const Instances * get_instances() const
static GeometrySet from_volume(Volume *volume, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
static void propagate_attributes_from_layer_to_instances(const AttributeAccessor src_attributes, MutableAttributeAccessor dst_attributes, const AttributeFilter &attribute_filter)
void replace_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
CurvesEditHints * get_curve_edit_hints_for_write()
void count_memory(MemoryCounter &memory) const
const PointCloud * get_pointcloud() const
const Mesh * get_mesh() const
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
GreasePencil * get_grease_pencil_for_write()
std::optional< Bounds< float3 > > compute_boundbox_without_instances() const
void attribute_foreach(Span< GeometryComponent::Type > component_types, bool include_instances, AttributeForeachCallback callback) const
void add(const GeometryComponent &component)
void replace_grease_pencil(GreasePencil *grease_pencil, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)