Blender V5.0
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 BLI_assert(!components_[size_t(component.type())]);
170 component.add_user();
171 components_[size_t(component.type())] = GeometryComponentPtr(
172 const_cast<GeometryComponent *>(&component));
173}
174
176{
178 for (const GeometryComponentPtr &component_ptr : components_) {
179 if (component_ptr) {
180 components.append(component_ptr.get());
181 }
182 }
183 return components;
184}
185
187 const bool use_radius, const bool use_subdiv) const
188{
189 std::optional<Bounds<float3>> bounds;
190 if (const PointCloud *pointcloud = this->get_pointcloud()) {
191 bounds = bounds::merge(bounds, pointcloud->bounds_min_max(use_radius));
192 }
193 if (const Mesh *mesh = this->get_mesh()) {
194 /* Use tessellated subdivision mesh if it exists. */
195 if (use_subdiv && mesh->runtime->mesh_eval) {
196 bounds = bounds::merge(bounds, mesh->runtime->mesh_eval->bounds_min_max());
197 }
198 else {
199 bounds = bounds::merge(bounds, mesh->bounds_min_max());
200 }
201 }
202 if (const Volume *volume = this->get_volume()) {
203 bounds = bounds::merge(bounds, BKE_volume_min_max(volume));
204 }
205 if (const Curves *curves_id = this->get_curves()) {
206 bounds = bounds::merge(bounds, curves_id->geometry.wrap().bounds_min_max(use_radius));
207 }
208 if (const GreasePencil *grease_pencil = this->get_grease_pencil()) {
209 bounds = bounds::merge(bounds, grease_pencil->bounds_min_max_eval(use_radius));
210 }
211 return bounds;
212}
213
214std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set)
215{
217 if (!geometry_set.name.empty()) {
218 parts.append(fmt::format("\"{}\"", geometry_set.name));
219 }
220 if (const Mesh *mesh = geometry_set.get_mesh()) {
221 parts.append(std::to_string(mesh->verts_num) + " verts");
222 parts.append(std::to_string(mesh->edges_num) + " edges");
223 parts.append(std::to_string(mesh->faces_num) + " faces");
224 parts.append(std::to_string(mesh->corners_num) + " corners");
225 if (mesh->runtime->subsurf_runtime_data) {
226 const int resolution = mesh->runtime->subsurf_runtime_data->resolution;
227 if (is_power_of_2_i(resolution - 1)) {
228 /* Display the resolution as subdiv levels if possible because that's more common. */
229 const int level = log2_floor(resolution - 1);
230 parts.append(std::to_string(level) + " subdiv levels");
231 }
232 else {
233 parts.append(std::to_string(resolution) + " subdiv resolution");
234 }
235 }
236 }
237 if (const Curves *curves = geometry_set.get_curves()) {
238 parts.append(std::to_string(curves->geometry.point_num) + " control points");
239 parts.append(std::to_string(curves->geometry.curve_num) + " curves");
240 }
241 if (const GreasePencil *grease_pencil = geometry_set.get_grease_pencil()) {
242 parts.append(std::to_string(grease_pencil->layers().size()) + " Grease Pencil layers");
243 }
244 if (const PointCloud *pointcloud = geometry_set.get_pointcloud()) {
245 parts.append(std::to_string(pointcloud->totpoint) + " points");
246 }
247 if (const Volume *volume = geometry_set.get_volume()) {
248 parts.append(std::to_string(BKE_volume_num_grids(volume)) + " volume grids");
249 }
250 if (geometry_set.has_instances()) {
251 parts.append(std::to_string(geometry_set.get_instances()->instances_num()) + " instances");
252 }
253 if (geometry_set.get_curve_edit_hints()) {
254 parts.append("curve edit hints");
255 }
256
257 stream << "<GeometrySet: ";
258 for (const int i : parts.index_range()) {
259 stream << parts[i];
260 if (i < parts.size() - 1) {
261 stream << ", ";
262 }
263 }
264 stream << ">";
265 return stream;
266}
267
269{
270 for (GeometryComponentPtr &component_ptr : components_) {
271 component_ptr.reset();
272 }
273}
274
276{
277 for (GeometryComponentPtr &component_ptr : components_) {
278 if (!component_ptr) {
279 continue;
280 }
281 if (component_ptr->owns_direct_data()) {
282 continue;
283 }
284 GeometryComponent &component_for_write = this->get_component_for_write(component_ptr->type());
285 component_for_write.ensure_owns_direct_data();
286 }
287}
288
290{
291 if (Instances *instances = this->get_instances_for_write()) {
292 instances->ensure_geometry_instances();
293 }
295}
296
298{
299 for (const GeometryComponentPtr &component_ptr : components_) {
300 if (component_ptr) {
301 if (!component_ptr->owns_direct_data()) {
302 return false;
303 }
304 }
305 }
306 return true;
307}
308
310{
311 for (const int i : IndexRange(this->components_.size())) {
312 if (components_[i]) {
314 }
315 }
316}
317
319{
320 const MeshComponent *component = this->get_component<MeshComponent>();
321 return (component == nullptr) ? nullptr : component->get();
322}
323
325{
326 const MeshComponent *component = this->get_component<MeshComponent>();
327 return component != nullptr && component->has_mesh();
328}
329
331{
333 return (component == nullptr) ? nullptr : component->get();
334}
335
337{
338 const VolumeComponent *component = this->get_component<VolumeComponent>();
339 return (component == nullptr) ? nullptr : component->get();
340}
341
343{
344 const CurveComponent *component = this->get_component<CurveComponent>();
345 return (component == nullptr) ? nullptr : component->get();
346}
347
349{
350 const InstancesComponent *component = this->get_component<InstancesComponent>();
351 return (component == nullptr) ? nullptr : component->get();
352}
353
355{
357 return (component == nullptr) ? nullptr : component->curves_edit_hints_.get();
358}
359
361{
363 return (component == nullptr) ? nullptr : component->grease_pencil_edit_hints_.get();
364}
365
367{
369 return (component == nullptr) ? nullptr : component->gizmo_edit_hints_.get();
370}
371
373{
375 return (component == nullptr) ? nullptr : component->get();
376}
377
379{
381 return component != nullptr && component->has_pointcloud();
382}
383
385{
386 const InstancesComponent *component = this->get_component<InstancesComponent>();
387 return component != nullptr && component->get() != nullptr &&
388 component->get()->instances_num() >= 1;
389}
390
392{
393 const VolumeComponent *component = this->get_component<VolumeComponent>();
394 return component != nullptr && component->has_volume();
395}
396
398{
399 const CurveComponent *component = this->get_component<CurveComponent>();
400 return component != nullptr && component->has_curves();
401}
402
404{
405 for (const GeometryComponentPtr &component_ptr : components_) {
406 if (component_ptr) {
407 if (!ELEM(component_ptr->type(),
410 {
411 return true;
412 }
413 }
414 }
415 return false;
416}
417
419{
421 return component != nullptr && component->has_grease_pencil();
422}
423
425{
426 return !(this->has_mesh() || this->has_curves() || this->has_pointcloud() ||
427 this->has_volume() || this->has_instances() || this->has_grease_pencil());
428}
429
431{
432 GeometrySet geometry_set;
433 geometry_set.replace_mesh(mesh, ownership);
434 return geometry_set;
435}
436
438{
439 GeometrySet geometry_set;
440 geometry_set.replace_volume(volume, ownership);
441 return geometry_set;
442}
443
445{
446 GeometrySet geometry_set;
447 geometry_set.replace_pointcloud(pointcloud, ownership);
448 return geometry_set;
449}
450
452{
453 GeometrySet geometry_set;
454 geometry_set.replace_curves(curves, ownership);
455 return geometry_set;
456}
457
459{
460 GeometrySet geometry_set;
461 geometry_set.replace_instances(instances, ownership);
462 return geometry_set;
463}
464
466 GeometryOwnershipType ownership)
467{
468 GeometrySet geometry_set;
469 geometry_set.replace_grease_pencil(grease_pencil, ownership);
470 return geometry_set;
471}
472
474{
475 if (mesh == nullptr) {
476 this->remove<MeshComponent>();
477 return;
478 }
479 if (mesh == this->get_mesh()) {
480 return;
481 }
482 this->remove<MeshComponent>();
484 component.replace(mesh, ownership);
485}
486
488{
489 if (curves == nullptr) {
491 return;
492 }
493 if (curves == this->get_curves()) {
494 return;
495 }
498 component.replace(curves, ownership);
499}
500
502{
503 if (instances == nullptr) {
505 return;
506 }
507 if (instances == this->get_instances()) {
508 return;
509 }
512 component.replace(instances, ownership);
513}
514
516{
517 if (pointcloud == nullptr) {
519 return;
520 }
521 if (pointcloud == this->get_pointcloud()) {
522 return;
523 }
526 component.replace(pointcloud, ownership);
527}
528
530{
531 if (volume == nullptr) {
533 return;
534 }
535 if (volume == this->get_volume()) {
536 return;
537 }
540 component.replace(volume, ownership);
541}
542
544 GeometryOwnershipType ownership)
545{
546 if (grease_pencil == nullptr) {
548 return;
549 }
550 if (grease_pencil == this->get_grease_pencil()) {
551 return;
552 }
555 component.replace(grease_pencil, ownership);
556}
557
559{
560 MeshComponent *component = this->get_component_ptr<MeshComponent>();
561 return component == nullptr ? nullptr : component->get_for_write();
562}
563
565{
566 PointCloudComponent *component = this->get_component_ptr<PointCloudComponent>();
567 return component == nullptr ? nullptr : component->get_for_write();
568}
569
571{
572 VolumeComponent *component = this->get_component_ptr<VolumeComponent>();
573 return component == nullptr ? nullptr : component->get_for_write();
574}
575
577{
578 CurveComponent *component = this->get_component_ptr<CurveComponent>();
579 return component == nullptr ? nullptr : component->get_for_write();
580}
581
583{
584 InstancesComponent *component = this->get_component_ptr<InstancesComponent>();
585 return component == nullptr ? nullptr : component->get_for_write();
586}
587
597
607
609{
610 if (!this->has<GeometryComponentEditData>()) {
611 return nullptr;
612 }
613 GeometryComponentEditData &component =
615 return component.gizmo_edit_hints_.get();
616}
617
619{
620 GreasePencilComponent *component = this->get_component_ptr<GreasePencilComponent>();
621 return component == nullptr ? nullptr : component->get_for_write();
622}
623
625{
626 for (const GeometryComponentPtr &component : components_) {
627 if (component) {
628 memory.add_shared(component.get(), [&](MemoryCounter &shared_memory) {
629 component->count_memory(shared_memory);
630 });
631 }
632 }
633}
634
636 const bool include_instances,
637 const AttributeForeachCallback callback) const
638{
639 for (const GeometryComponent::Type component_type : component_types) {
640 if (!this->has(component_type)) {
641 continue;
642 }
643 const GeometryComponent &component = *this->get_component(component_type);
644 const std::optional<AttributeAccessor> attributes = component.attributes();
645 if (attributes.has_value()) {
646 attributes->foreach_attribute([&](const AttributeIter &iter) {
647 callback(iter.name, {iter.domain, iter.data_type}, component);
648 });
649 }
650 /* For Grease Pencil, we also need to iterate over the attributes of the evaluated drawings. */
651 if (component_type == GeometryComponent::Type::GreasePencil) {
652 const GreasePencil &grease_pencil = *this->get_grease_pencil();
653 for (const bke::greasepencil::Layer *layer : grease_pencil.layers()) {
654 if (const bke::greasepencil::Drawing *drawing = grease_pencil.get_eval_drawing(*layer)) {
655 const AttributeAccessor attributes = drawing->strokes().attributes();
656 attributes.foreach_attribute([&](const AttributeIter &iter) {
657 callback(iter.name, {iter.domain, iter.data_type}, component);
658 });
659 }
660 }
661 }
662 }
663 if (include_instances && this->has_instances()) {
664 const Instances &instances = *this->get_instances();
665 instances.foreach_referenced_geometry([&](const GeometrySet &instance_geometry_set) {
666 instance_geometry_set.attribute_foreach(component_types, include_instances, callback);
667 });
668 }
669}
670
672 const StringRef name)
673{
674 switch (type) {
676 static auto component = GeometryComponent::create(type);
677 return component->attributes()->is_builtin(name);
678 }
680 static auto component = GeometryComponent::create(type);
681 return component->attributes()->is_builtin(name);
682 }
684 static auto component = GeometryComponent::create(type);
685 return component->attributes()->is_builtin(name);
686 }
688 static auto component = GeometryComponent::create(type);
689 return component->attributes()->is_builtin(name);
690 }
692 static auto grease_pencil_component = GeometryComponent::create(
694 static auto curves_component = GeometryComponent::create(GeometryComponent::Type::Curve);
695 return grease_pencil_component->attributes()->is_builtin(name) ||
696 curves_component->attributes()->is_builtin(name);
697 }
700 return false;
701 }
702 }
704 return false;
705}
706
708{
709 const int index = this->names.index_of_or_add(name);
710 if (index >= this->kinds.size()) {
711 this->kinds.append(AttributeDomainAndType{kind.domain, kind.data_type});
712 }
713 else {
714 this->kinds[index].domain = bke::attribute_domain_highest_priority(
715 {this->kinds[index].domain, kind.domain});
716 this->kinds[index].data_type = bke::attribute_data_type_highest_complexity(
717 {this->kinds[index].data_type, kind.data_type});
718 }
719}
720
722 const Span<GeometryComponent::Type> component_types,
723 const GeometryComponent::Type dst_component_type,
724 bool include_instances,
725 const AttributeFilter &attribute_filter,
726 GatheredAttributes &r_attributes) const
727{
728 this->attribute_foreach(
729 component_types,
730 include_instances,
731 [&](const StringRef attribute_id,
732 const AttributeMetaData &meta_data,
733 const GeometryComponent &component) {
734 if (component.attributes()->is_builtin(attribute_id)) {
735 if (!attribute_is_builtin_on_component_type(dst_component_type, attribute_id)) {
736 /* Don't propagate built-in attributes that are not built-in on the destination
737 * component. */
738 return;
739 }
740 }
741 if (meta_data.data_type == AttrType::String) {
742 /* Propagating string attributes is not supported yet. */
743 return;
744 }
745 if (attribute_filter.allow_skip(attribute_id)) {
746 return;
747 }
748
749 AttrDomain domain = meta_data.domain;
750 if (dst_component_type != GeometryComponent::Type::Instance &&
751 domain == AttrDomain::Instance) {
752 domain = AttrDomain::Point;
753 }
754
755 r_attributes.add(attribute_id, AttributeDomainAndType{domain, meta_data.data_type});
756 });
757}
758
759static void gather_component_types_recursive(const GeometrySet &geometry_set,
760 const bool include_instances,
761 const bool ignore_empty,
763{
764 for (const GeometryComponent *component : geometry_set.get_components()) {
765 if (ignore_empty) {
766 if (component->is_empty()) {
767 continue;
768 }
769 }
770 r_types.append_non_duplicates(component->type());
771 }
772 if (!include_instances) {
773 return;
774 }
775 const Instances *instances = geometry_set.get_instances();
776 if (instances == nullptr) {
777 return;
778 }
779 instances->foreach_referenced_geometry([&](const GeometrySet &instance_geometry_set) {
781 instance_geometry_set, include_instances, ignore_empty, r_types);
782 });
783}
784
786 bool ignore_empty) const
787{
789 gather_component_types_recursive(*this, include_instances, ignore_empty, types);
790 return types;
791}
792
794{
795 const GeometrySet *geometry_set = object.runtime->geometry_set_eval;
796 if (geometry_set == nullptr) {
797 return false;
798 }
799 if (geometry_set->has_component<InstancesComponent>()) {
800 return true;
801 }
802 if (object.type != OB_MESH && geometry_set->has_component<MeshComponent>()) {
803 return true;
804 }
805 if (object.type != OB_POINTCLOUD && geometry_set->has_component<PointCloudComponent>()) {
806 return true;
807 }
808 if (object.type != OB_VOLUME && geometry_set->has_component<VolumeComponent>()) {
809 return true;
810 }
811 if (!ELEM(object.type, OB_CURVES_LEGACY, OB_FONT) &&
812 geometry_set->has_component<CurveComponent>())
813 {
814 return true;
815 }
816 if (object.type != OB_GREASE_PENCIL && geometry_set->has_component<GreasePencilComponent>()) {
817 return true;
818 }
819 return false;
820}
821
823
824} // 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(...)
Object is a sort of wrapper for general info.
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
constexpr bool contains(const T &value) const
Definition BLI_span.hh:277
void append(const T &value)
IndexRange index_range() const
void append_non_duplicates(const T &value)
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)
void foreach_referenced_geometry(FunctionRef< void(const GeometrySet &geometry_set)> callback) const
int instances_num() const
Definition instances.cc:393
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)
bool attribute_is_builtin_on_component_type(const GeometryComponent::Type type, StringRef name)
AttrType attribute_data_type_highest_complexity(Span< AttrType > 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
const char * name
bool allow_skip(const StringRef name) const
void add(const StringRef name, const AttributeDomainAndType &kind)
Vector< AttributeDomainAndType, 16 > kinds
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
FunctionRef< void(StringRef attribute_id, const AttributeMetaData &meta_data, const GeometryComponent &component)> AttributeForeachCallback
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)
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)
void gather_attributes_for_propagation(Span< GeometryComponent::Type > component_types, GeometryComponent::Type dst_component_type, bool include_instances, const AttributeFilter &attribute_filter, GatheredAttributes &r_attributes) const
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 count_memory(MemoryCounter &memory) const
const GreasePencilEditHints * get_grease_pencil_edit_hints() 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()
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
void add(const GeometryComponent &component)
void replace_grease_pencil(GreasePencil *grease_pencil, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
i
Definition text_draw.cc:230