Blender V4.5
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 <fmt/format.h>
6
7#include "BLI_bounds.hh"
8#include "BLI_map.hh"
10#include "BLI_task.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_mesh.hh"
19#include "BKE_modifier.hh"
20#include "BKE_object_types.hh"
22#include "BKE_volume.hh"
23
24#include "DNA_object_types.h"
26
27namespace blender::bke {
28
29/* -------------------------------------------------------------------- */
32
34
36{
37 switch (component_type) {
38 case Type::Mesh:
42 case Type::Instance:
44 case Type::Volume:
46 case Type::Curve:
48 case Type::Edit:
52 }
54 return {};
55}
56
58{
59 if (this->is_empty()) {
60 return 0;
61 }
62 const std::optional<AttributeAccessor> attributes = this->attributes();
63 if (attributes.has_value()) {
64 return attributes->domain_size(domain);
65 }
66 return 0;
67}
68
69std::optional<AttributeAccessor> GeometryComponent::attributes() const
70{
71 return std::nullopt;
72};
73std::optional<MutableAttributeAccessor> GeometryComponent::attributes_for_write()
74{
75 return std::nullopt;
76}
77
79
81{
82 return type_;
83}
84
86{
87 return false;
88}
89
90void GeometryComponent::delete_self()
91{
92 delete this;
93}
94
95void GeometryComponent::delete_data_only()
96{
97 this->clear();
98}
99
101
102/* -------------------------------------------------------------------- */
105
106GeometrySet::GeometrySet() = default;
107GeometrySet::GeometrySet(const GeometrySet &other) = default;
108GeometrySet::GeometrySet(GeometrySet &&other) = default;
109GeometrySet::~GeometrySet() = default;
110GeometrySet &GeometrySet::operator=(const GeometrySet &other) = default;
112
114{
115 GeometryComponentPtr &component_ptr = components_[size_t(component_type)];
116 if (!component_ptr) {
117 /* If the component did not exist before, create a new one. */
118 component_ptr = GeometryComponent::create(component_type);
119 }
120 else if (component_ptr->is_mutable()) {
121 /* If the referenced component is already mutable, return it directly. */
122 component_ptr->tag_ensured_mutable();
123 }
124 else {
125 /* If the referenced component is shared, make a copy. The copy is not shared and is
126 * therefore mutable. */
127 component_ptr = component_ptr->copy();
128 }
129 return const_cast<GeometryComponent &>(*component_ptr);
130}
131
132GeometryComponent *GeometrySet::get_component_ptr(GeometryComponent::Type type)
133{
134 if (this->has(type)) {
135 return &this->get_component_for_write(type);
136 }
137 return nullptr;
138}
139
141{
142 return components_[size_t(component_type)].get();
143}
144
145bool GeometrySet::has(const GeometryComponent::Type component_type) const
146{
147 const GeometryComponentPtr &component = components_[size_t(component_type)];
148 return component.has_value() && !component->is_empty();
149}
150
152{
153 components_[size_t(component_type)].reset();
154}
155
157{
158 for (GeometryComponentPtr &component_ptr : components_) {
159 if (component_ptr) {
160 if (!component_types.contains(component_ptr->type())) {
161 component_ptr.reset();
162 }
163 }
164 }
165}
166
168{
169 Vector<GeometryComponent::Type> extended_types = component_types;
172 this->keep_only(extended_types);
173}
174
179
181{
182 BLI_assert(!components_[size_t(component.type())]);
183 component.add_user();
184 components_[size_t(component.type())] = GeometryComponentPtr(
185 const_cast<GeometryComponent *>(&component));
186}
187
189{
191 for (const GeometryComponentPtr &component_ptr : components_) {
192 if (component_ptr) {
193 components.append(component_ptr.get());
194 }
195 }
196 return components;
197}
198
200 const bool use_radius, const bool use_subdiv) const
201{
202 std::optional<Bounds<float3>> bounds;
203 if (const PointCloud *pointcloud = this->get_pointcloud()) {
204 bounds = bounds::merge(bounds, pointcloud->bounds_min_max(use_radius));
205 }
206 if (const Mesh *mesh = this->get_mesh()) {
207 /* Use tessellated subdivision mesh if it exists. */
208 if (use_subdiv && mesh->runtime->mesh_eval) {
209 bounds = bounds::merge(bounds, mesh->runtime->mesh_eval->bounds_min_max());
210 }
211 else {
212 bounds = bounds::merge(bounds, mesh->bounds_min_max());
213 }
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(use_radius));
220 }
221 if (const GreasePencil *grease_pencil = this->get_grease_pencil()) {
222 bounds = bounds::merge(bounds, grease_pencil->bounds_min_max_eval(use_radius));
223 }
224 return bounds;
225}
226
227std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set)
228{
230 if (!geometry_set.name.empty()) {
231 parts.append(fmt::format("\"{}\"", geometry_set.name));
232 }
233 if (const Mesh *mesh = geometry_set.get_mesh()) {
234 parts.append(std::to_string(mesh->verts_num) + " verts");
235 parts.append(std::to_string(mesh->edges_num) + " edges");
236 parts.append(std::to_string(mesh->faces_num) + " faces");
237 parts.append(std::to_string(mesh->corners_num) + " corners");
238 if (mesh->runtime->subsurf_runtime_data) {
239 const int resolution = mesh->runtime->subsurf_runtime_data->resolution;
240 if (is_power_of_2_i(resolution - 1)) {
241 /* Display the resolution as subdiv levels if possible because that's more common. */
242 const int level = log2_floor(resolution - 1);
243 parts.append(std::to_string(level) + " subdiv levels");
244 }
245 else {
246 parts.append(std::to_string(resolution) + " subdiv resolution");
247 }
248 }
249 }
250 if (const Curves *curves = geometry_set.get_curves()) {
251 parts.append(std::to_string(curves->geometry.point_num) + " control points");
252 parts.append(std::to_string(curves->geometry.curve_num) + " curves");
253 }
254 if (const GreasePencil *grease_pencil = geometry_set.get_grease_pencil()) {
255 parts.append(std::to_string(grease_pencil->layers().size()) + " Grease Pencil layers");
256 }
257 if (const PointCloud *pointcloud = geometry_set.get_pointcloud()) {
258 parts.append(std::to_string(pointcloud->totpoint) + " points");
259 }
260 if (const Volume *volume = geometry_set.get_volume()) {
261 parts.append(std::to_string(BKE_volume_num_grids(volume)) + " volume grids");
262 }
263 if (geometry_set.has_instances()) {
264 parts.append(std::to_string(geometry_set.get_instances()->instances_num()) + " instances");
265 }
266 if (geometry_set.get_curve_edit_hints()) {
267 parts.append("curve edit hints");
268 }
269
270 stream << "<GeometrySet: ";
271 for (const int i : parts.index_range()) {
272 stream << parts[i];
273 if (i < parts.size() - 1) {
274 stream << ", ";
275 }
276 }
277 stream << ">";
278 return stream;
279}
280
282{
283 for (GeometryComponentPtr &component_ptr : components_) {
284 component_ptr.reset();
285 }
286}
287
289{
290 for (GeometryComponentPtr &component_ptr : components_) {
291 if (!component_ptr) {
292 continue;
293 }
294 if (component_ptr->owns_direct_data()) {
295 continue;
296 }
297 GeometryComponent &component_for_write = this->get_component_for_write(component_ptr->type());
298 component_for_write.ensure_owns_direct_data();
299 }
300}
301
303{
304 if (Instances *instances = this->get_instances_for_write()) {
305 instances->ensure_geometry_instances();
306 }
308}
309
311{
312 for (const GeometryComponentPtr &component_ptr : components_) {
313 if (component_ptr) {
314 if (!component_ptr->owns_direct_data()) {
315 return false;
316 }
317 }
318 }
319 return true;
320}
321
323{
324 for (const int i : IndexRange(this->components_.size())) {
325 if (components_[i]) {
327 }
328 }
329}
330
332{
333 const MeshComponent *component = this->get_component<MeshComponent>();
334 return (component == nullptr) ? nullptr : component->get();
335}
336
338{
339 const MeshComponent *component = this->get_component<MeshComponent>();
340 return component != nullptr && component->has_mesh();
341}
342
344{
346 return (component == nullptr) ? nullptr : component->get();
347}
348
350{
351 const VolumeComponent *component = this->get_component<VolumeComponent>();
352 return (component == nullptr) ? nullptr : component->get();
353}
354
356{
357 const CurveComponent *component = this->get_component<CurveComponent>();
358 return (component == nullptr) ? nullptr : component->get();
359}
360
362{
363 const InstancesComponent *component = this->get_component<InstancesComponent>();
364 return (component == nullptr) ? nullptr : component->get();
365}
366
368{
370 return (component == nullptr) ? nullptr : component->curves_edit_hints_.get();
371}
372
374{
376 return (component == nullptr) ? nullptr : component->grease_pencil_edit_hints_.get();
377}
378
380{
382 return (component == nullptr) ? nullptr : component->gizmo_edit_hints_.get();
383}
384
386{
388 return (component == nullptr) ? nullptr : component->get();
389}
390
392{
394 return component != nullptr && component->has_pointcloud();
395}
396
398{
399 const InstancesComponent *component = this->get_component<InstancesComponent>();
400 return component != nullptr && component->get() != nullptr &&
401 component->get()->instances_num() >= 1;
402}
403
405{
406 const VolumeComponent *component = this->get_component<VolumeComponent>();
407 return component != nullptr && component->has_volume();
408}
409
411{
412 const CurveComponent *component = this->get_component<CurveComponent>();
413 return component != nullptr && component->has_curves();
414}
415
417{
418 for (const GeometryComponentPtr &component_ptr : components_) {
419 if (component_ptr) {
420 if (component_ptr->type() != GeometryComponent::Type::Instance) {
421 return true;
422 }
423 }
424 }
425 return false;
426}
427
429{
431 return component != nullptr && component->has_grease_pencil();
432}
433
435{
436 return !(this->has_mesh() || this->has_curves() || this->has_pointcloud() ||
437 this->has_volume() || this->has_instances() || this->has_grease_pencil());
438}
439
441{
442 GeometrySet geometry_set;
443 geometry_set.replace_mesh(mesh, ownership);
444 return geometry_set;
445}
446
448{
449 GeometrySet geometry_set;
450 geometry_set.replace_volume(volume, ownership);
451 return geometry_set;
452}
453
455{
456 GeometrySet geometry_set;
457 geometry_set.replace_pointcloud(pointcloud, ownership);
458 return geometry_set;
459}
460
462{
463 GeometrySet geometry_set;
464 geometry_set.replace_curves(curves, ownership);
465 return geometry_set;
466}
467
469{
470 GeometrySet geometry_set;
471 geometry_set.replace_instances(instances, ownership);
472 return geometry_set;
473}
474
476 GeometryOwnershipType ownership)
477{
478 GeometrySet geometry_set;
479 geometry_set.replace_grease_pencil(grease_pencil, ownership);
480 return geometry_set;
481}
482
484{
485 if (mesh == nullptr) {
486 this->remove<MeshComponent>();
487 return;
488 }
489 if (mesh == this->get_mesh()) {
490 return;
491 }
492 this->remove<MeshComponent>();
494 component.replace(mesh, ownership);
495}
496
498{
499 if (curves == nullptr) {
501 return;
502 }
503 if (curves == this->get_curves()) {
504 return;
505 }
508 component.replace(curves, ownership);
509}
510
512{
513 if (instances == nullptr) {
515 return;
516 }
517 if (instances == this->get_instances()) {
518 return;
519 }
522 component.replace(instances, ownership);
523}
524
526{
527 if (pointcloud == nullptr) {
529 return;
530 }
531 if (pointcloud == this->get_pointcloud()) {
532 return;
533 }
536 component.replace(pointcloud, ownership);
537}
538
540{
541 if (volume == nullptr) {
543 return;
544 }
545 if (volume == this->get_volume()) {
546 return;
547 }
550 component.replace(volume, ownership);
551}
552
554 GeometryOwnershipType ownership)
555{
556 if (grease_pencil == nullptr) {
558 return;
559 }
560 if (grease_pencil == this->get_grease_pencil()) {
561 return;
562 }
565 component.replace(grease_pencil, ownership);
566}
567
569{
570 MeshComponent *component = this->get_component_ptr<MeshComponent>();
571 return component == nullptr ? nullptr : component->get_for_write();
572}
573
575{
576 PointCloudComponent *component = this->get_component_ptr<PointCloudComponent>();
577 return component == nullptr ? nullptr : component->get_for_write();
578}
579
581{
582 VolumeComponent *component = this->get_component_ptr<VolumeComponent>();
583 return component == nullptr ? nullptr : component->get_for_write();
584}
585
587{
588 CurveComponent *component = this->get_component_ptr<CurveComponent>();
589 return component == nullptr ? nullptr : component->get_for_write();
590}
591
593{
594 InstancesComponent *component = this->get_component_ptr<InstancesComponent>();
595 return component == nullptr ? nullptr : component->get_for_write();
596}
597
607
617
619{
620 if (!this->has<GeometryComponentEditData>()) {
621 return nullptr;
622 }
623 GeometryComponentEditData &component =
625 return component.gizmo_edit_hints_.get();
626}
627
629{
630 GreasePencilComponent *component = this->get_component_ptr<GreasePencilComponent>();
631 return component == nullptr ? nullptr : component->get_for_write();
632}
633
635{
636 for (const GeometryComponentPtr &component : components_) {
637 if (component) {
638 memory.add_shared(component.get(), [&](MemoryCounter &shared_memory) {
639 component->count_memory(shared_memory);
640 });
641 }
642 }
643}
644
646 const bool include_instances,
647 const AttributeForeachCallback callback) const
648{
649 for (const GeometryComponent::Type component_type : component_types) {
650 if (!this->has(component_type)) {
651 continue;
652 }
653 const GeometryComponent &component = *this->get_component(component_type);
654 const std::optional<AttributeAccessor> attributes = component.attributes();
655 if (attributes.has_value()) {
656 attributes->foreach_attribute([&](const AttributeIter &iter) {
657 callback(iter.name, {iter.domain, iter.data_type}, component);
658 });
659 }
660 /* For Grease Pencil, we also need to iterate over the attributes of the evaluated drawings. */
661 if (component_type == GeometryComponent::Type::GreasePencil) {
662 const GreasePencil &grease_pencil = *this->get_grease_pencil();
663 for (const bke::greasepencil::Layer *layer : grease_pencil.layers()) {
664 if (const bke::greasepencil::Drawing *drawing = grease_pencil.get_eval_drawing(*layer)) {
665 const AttributeAccessor attributes = drawing->strokes().attributes();
666 attributes.foreach_attribute([&](const AttributeIter &iter) {
667 callback(iter.name, {iter.domain, iter.data_type}, component);
668 });
669 }
670 }
671 }
672 }
673 if (include_instances && this->has_instances()) {
674 const Instances &instances = *this->get_instances();
675 instances.foreach_referenced_geometry([&](const GeometrySet &instance_geometry_set) {
676 instance_geometry_set.attribute_foreach(component_types, include_instances, callback);
677 });
678 }
679}
680
682 const StringRef name)
683{
684 switch (type) {
686 static auto component = GeometryComponent::create(type);
687 return component->attributes()->is_builtin(name);
688 }
690 static auto component = GeometryComponent::create(type);
691 return component->attributes()->is_builtin(name);
692 }
694 static auto component = GeometryComponent::create(type);
695 return component->attributes()->is_builtin(name);
696 }
698 static auto component = GeometryComponent::create(type);
699 return component->attributes()->is_builtin(name);
700 }
702 static auto grease_pencil_component = GeometryComponent::create(
704 static auto curves_component = GeometryComponent::create(GeometryComponent::Type::Curve);
705 return grease_pencil_component->attributes()->is_builtin(name) ||
706 curves_component->attributes()->is_builtin(name);
707 }
710 return false;
711 }
712 }
714 return false;
715}
716
718 const Span<GeometryComponent::Type> component_types,
719 const GeometryComponent::Type dst_component_type,
720 bool include_instances,
721 const AttributeFilter &attribute_filter,
722 Map<StringRef, AttributeDomainAndType> &r_attributes) const
723{
724 this->attribute_foreach(
725 component_types,
726 include_instances,
727 [&](const StringRef attribute_id,
728 const AttributeMetaData &meta_data,
729 const GeometryComponent &component) {
730 if (component.attributes()->is_builtin(attribute_id)) {
731 if (!attribute_is_builtin_on_component_type(dst_component_type, attribute_id)) {
732 /* Don't propagate built-in attributes that are not built-in on the destination
733 * component. */
734 return;
735 }
736 }
737 if (meta_data.data_type == CD_PROP_STRING) {
738 /* Propagating string attributes is not supported yet. */
739 return;
740 }
741 if (attribute_filter.allow_skip(attribute_id)) {
742 return;
743 }
744
745 AttrDomain domain = meta_data.domain;
746 if (dst_component_type != GeometryComponent::Type::Instance &&
747 domain == AttrDomain::Instance) {
748 domain = AttrDomain::Point;
749 }
750
751 auto add_info = [&](AttributeDomainAndType *attribute_kind) {
752 attribute_kind->domain = domain;
753 attribute_kind->data_type = meta_data.data_type;
754 };
755 auto modify_info = [&](AttributeDomainAndType *attribute_kind) {
756 attribute_kind->domain = bke::attribute_domain_highest_priority(
757 {attribute_kind->domain, domain});
758 attribute_kind->data_type = bke::attribute_data_type_highest_complexity(
759 {attribute_kind->data_type, meta_data.data_type});
760 };
761 r_attributes.add_or_modify(attribute_id, add_info, modify_info);
762 });
763}
764
765static void gather_component_types_recursive(const GeometrySet &geometry_set,
766 const bool include_instances,
767 const bool ignore_empty,
769{
770 for (const GeometryComponent *component : geometry_set.get_components()) {
771 if (ignore_empty) {
772 if (component->is_empty()) {
773 continue;
774 }
775 }
776 r_types.append_non_duplicates(component->type());
777 }
778 if (!include_instances) {
779 return;
780 }
781 const Instances *instances = geometry_set.get_instances();
782 if (instances == nullptr) {
783 return;
784 }
785 instances->foreach_referenced_geometry([&](const GeometrySet &instance_geometry_set) {
787 instance_geometry_set, include_instances, ignore_empty, r_types);
788 });
789}
790
792 bool ignore_empty) const
793{
795 gather_component_types_recursive(*this, include_instances, ignore_empty, types);
796 return types;
797}
798
800 Vector<GeometrySet *> &r_geometry_sets)
801{
802 r_geometry_sets.append(&geometry_set);
803 if (!geometry_set.has_instances()) {
804 return;
805 }
806 /* In the future this can be improved by deduplicating instance references across different
807 * instances. */
808 Instances &instances = *geometry_set.get_instances_for_write();
809 instances.ensure_geometry_instances();
810 for (const int handle : instances.references().index_range()) {
811 if (instances.references()[handle].type() == InstanceReference::Type::GeometrySet) {
812 GeometrySet &instance_geometry = instances.geometry_set_from_reference(handle);
813 gather_mutable_geometry_sets(instance_geometry, r_geometry_sets);
814 }
815 }
816}
817
819{
820 Vector<GeometrySet *> geometry_sets;
821 gather_mutable_geometry_sets(*this, geometry_sets);
822 if (geometry_sets.size() == 1) {
823 /* Avoid possible overhead and a large call stack when multithreading is pointless. */
824 callback(*geometry_sets.first());
825 }
826 else {
827 threading::parallel_for_each(geometry_sets,
828 [&](GeometrySet *geometry_set) { callback(*geometry_set); });
829 }
830}
831
833{
834 const GeometrySet *geometry_set = object.runtime->geometry_set_eval;
835 if (geometry_set == nullptr) {
836 return false;
837 }
838 if (geometry_set->has_component<InstancesComponent>()) {
839 return true;
840 }
841 if (object.type != OB_MESH && geometry_set->has_component<MeshComponent>()) {
842 return true;
843 }
844 if (object.type != OB_POINTCLOUD && geometry_set->has_component<PointCloudComponent>()) {
845 return true;
846 }
847 if (object.type != OB_VOLUME && geometry_set->has_component<VolumeComponent>()) {
848 return true;
849 }
850 if (!ELEM(object.type, OB_CURVES_LEGACY, OB_FONT) &&
851 geometry_set->has_component<CurveComponent>())
852 {
853 return true;
854 }
855 if (object.type != OB_GREASE_PENCIL && geometry_set->has_component<GreasePencilComponent>()) {
856 return true;
857 }
858 return false;
859}
860
862
863} // namespace blender::bke
Low-level operations for curves.
Low-level operations for grease pencil.
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:93
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE int is_power_of_2_i(int n)
#define ELEM(...)
@ 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
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
Definition BLI_map.hh:481
constexpr bool contains(const T &value) const
Definition BLI_span.hh:277
int64_t size() const
void append(const T &value)
IndexRange index_range() const
void append_non_duplicates(const T &value)
const T & first() const
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
void replace(Curves *curve, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
std::unique_ptr< GreasePencilEditHints > grease_pencil_edit_hints_
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)
GeometrySet & geometry_set_from_reference(int reference_index)
Definition instances.cc:251
Span< InstanceReference > references() const
Definition instances.cc:285
void foreach_referenced_geometry(FunctionRef< void(const GeometrySet &geometry_set)> callback) const
int instances_num() const
Definition instances.cc:398
void replace(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
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)
static char ** types
Definition makesdna.cc:71
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:26
void parallel_for_each(Range &&range, const Function &function)
Definition BLI_task.hh:56
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)
FunctionRef< void(StringRef attribute_id, const AttributeMetaData &meta_data, const GeometryComponent &component)> AttributeForeachCallback
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
std::optional< Bounds< float3 > > compute_boundbox_without_instances(bool use_radius=true, bool use_subdiv=false) const
static GeometrySet from_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
bool has(const GeometryComponent::Type component_type) 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)
GreasePencilEditHints * get_grease_pencil_edit_hints_for_write()
void replace_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
CurvesEditHints * get_curve_edit_hints_for_write()
void gather_attributes_for_propagation(Span< GeometryComponent::Type > component_types, GeometryComponent::Type dst_component_type, bool include_instances, const AttributeFilter &attribute_filter, Map< StringRef, AttributeDomainAndType > &r_attributes) const
void count_memory(MemoryCounter &memory) const
const GreasePencilEditHints * get_grease_pencil_edit_hints() const
const PointCloud * get_pointcloud() const
const Mesh * get_mesh() const
void modify_geometry_sets(ForeachSubGeometryCallback callback)
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
GreasePencil * get_grease_pencil_for_write()
Vector< GeometryComponent::Type > gather_component_types(bool include_instances, bool ignore_empty) const
void attribute_foreach(Span< GeometryComponent::Type > component_types, bool include_instances, AttributeForeachCallback callback) const
FunctionRef< void(GeometrySet &geometry_set)> ForeachSubGeometryCallback
void add(const GeometryComponent &component)
void replace_grease_pencil(GreasePencil *grease_pencil, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
i
Definition text_draw.cc:230