Blender V4.3
spreadsheet_data_source_geometry.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_math_matrix.hh"
7
8#include "BKE_attribute.hh"
10#include "BKE_context.hh"
11#include "BKE_curves.hh"
12#include "BKE_editmesh.hh"
14#include "BKE_geometry_set.hh"
16#include "BKE_global.hh"
17#include "BKE_grease_pencil.hh"
18#include "BKE_instances.hh"
19#include "BKE_lib_id.hh"
20#include "BKE_mesh.hh"
21#include "BKE_mesh_wrapper.hh"
22#include "BKE_modifier.hh"
24#include "BKE_object_types.hh"
25#include "BKE_volume.hh"
26#include "BKE_volume_grid.hh"
27
28#include "DNA_ID.h"
30#include "DNA_space_types.h"
31#include "DNA_userdef_types.h"
32
34
35#include "ED_curves.hh"
36#include "ED_outliner.hh"
37#include "ED_spreadsheet.hh"
38
41
42#include "BLT_translation.hh"
43
44#include "RNA_access.hh"
45#include "RNA_enum_types.hh"
46
47#include "UI_resources.hh"
48
49#include "bmesh.hh"
50
52#include "spreadsheet_intern.hh"
53
55
57
59 FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const
60{
61 for (const auto item : columns_.items()) {
62 SpreadsheetColumnID column_id;
63 column_id.name = (char *)item.key.c_str();
64 fn(column_id, true);
65 }
66}
67
68std::unique_ptr<ColumnValues> ExtraColumns::get_column_values(
69 const SpreadsheetColumnID &column_id) const
70{
71 const GSpan *values = columns_.lookup_ptr(column_id.name);
72 if (values == nullptr) {
73 return {};
74 }
75 return std::make_unique<ColumnValues>(column_id.name, GVArray::ForSpan(*values));
76}
77
79 const Mesh &mesh,
80 const bke::AttrDomain domain,
81 FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn)
82{
83 switch (domain) {
85 if (CustomData_has_layer(&mesh.vert_data, CD_ORIGINDEX)) {
86 fn({(char *)"Original Index"}, false);
87 }
88 break;
90 if (CustomData_has_layer(&mesh.edge_data, CD_ORIGINDEX)) {
91 fn({(char *)"Original Index"}, false);
92 }
93 fn({(char *)"Vertices"}, false);
94 break;
96 if (CustomData_has_layer(&mesh.face_data, CD_ORIGINDEX)) {
97 fn({(char *)"Original Index"}, false);
98 }
99 fn({(char *)"Corner Start"}, false);
100 fn({(char *)"Corner Size"}, false);
101 break;
103 fn({(char *)"Vertex"}, false);
104 fn({(char *)"Edge"}, false);
105 break;
106 default:
108 break;
109 }
110}
111
112static std::unique_ptr<ColumnValues> build_mesh_debug_columns(const Mesh &mesh,
113 const bke::AttrDomain domain,
114 const StringRef name)
115{
116 switch (domain) {
118 if (name == "Original Index") {
119 const int *data = static_cast<const int *>(
120 CustomData_get_layer(&mesh.vert_data, CD_ORIGINDEX));
121 if (data) {
122 return std::make_unique<ColumnValues>(name,
123 VArray<int>::ForSpan({data, mesh.verts_num}));
124 }
125 }
126 return {};
127 }
129 if (name == "Original Index") {
130 const int *data = static_cast<const int *>(
131 CustomData_get_layer(&mesh.edge_data, CD_ORIGINDEX));
132 if (data) {
133 return std::make_unique<ColumnValues>(name,
134 VArray<int>::ForSpan({data, mesh.edges_num}));
135 }
136 }
137 if (name == "Vertices") {
138 return std::make_unique<ColumnValues>(name, VArray<int2>::ForSpan(mesh.edges()));
139 }
140 return {};
141 }
143 if (name == "Original Index") {
144 const int *data = static_cast<const int *>(
145 CustomData_get_layer(&mesh.face_data, CD_ORIGINDEX));
146 if (data) {
147 return std::make_unique<ColumnValues>(name,
148 VArray<int>::ForSpan({data, mesh.faces_num}));
149 }
150 }
151 if (name == "Corner Start") {
152 return std::make_unique<ColumnValues>(
153 name, VArray<int>::ForSpan(mesh.face_offsets().drop_back(1)));
154 }
155 if (name == "Corner Size") {
156 const OffsetIndices faces = mesh.faces();
157 return std::make_unique<ColumnValues>(
158 name, VArray<int>::ForFunc(faces.size(), [faces](int64_t index) {
159 return faces[index].size();
160 }));
161 }
162 return {};
163 }
165 if (name == "Vertex") {
166 return std::make_unique<ColumnValues>(name, VArray<int>::ForSpan(mesh.corner_verts()));
167 }
168 if (name == "Edge") {
169 return std::make_unique<ColumnValues>(name, VArray<int>::ForSpan(mesh.corner_edges()));
170 }
171 return {};
172 }
173 default:
175 return {};
176 }
177}
178
180 FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const
181{
182 std::optional<const bke::AttributeAccessor> attributes = this->get_component_attributes();
183 if (!attributes.has_value()) {
184 return;
185 }
186 if (attributes->domain_size(domain_) == 0) {
187 return;
188 }
189
190 if (component_->type() == bke::GeometryComponent::Type::Instance) {
191 fn({(char *)"Name"}, false);
192 }
193
195 fn({(char *)"Name"}, false);
196 }
197
198 extra_columns_.foreach_default_column_ids(fn);
199
200 attributes->foreach_attribute([&](const bke::AttributeIter &iter) {
201 if (iter.domain != domain_) {
202 return;
203 }
205 return;
206 }
208 return;
209 }
210 if (iter.domain == bke::AttrDomain::Instance && iter.name == "instance_transform") {
211 /* Don't display the instance transform attribute, since matrix visualization in the
212 * spreadsheet isn't helpful. */
213 return;
214 }
215 SpreadsheetColumnID column_id;
216 column_id.name = (char *)iter.name.data();
217 const bool is_front = iter.name == ".viewer";
218 fn(column_id, is_front);
219 });
220
221 if (component_->type() == bke::GeometryComponent::Type::Instance) {
222 fn({(char *)"Position"}, false);
223 fn({(char *)"Rotation"}, false);
224 fn({(char *)"Scale"}, false);
225 }
226 else if (G.debug_value == 4001 && component_->type() == bke::GeometryComponent::Type::Mesh) {
227 const bke::MeshComponent &component = static_cast<const bke::MeshComponent &>(*component_);
228 if (const Mesh *mesh = component.get()) {
229 add_mesh_debug_column_names(*mesh, domain_, fn);
230 }
231 }
232}
233
234std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
235 const SpreadsheetColumnID &column_id) const
236{
237 std::optional<const bke::AttributeAccessor> attributes = this->get_component_attributes();
238 if (!attributes.has_value()) {
239 return {};
240 }
241 const int domain_num = attributes->domain_size(domain_);
242 if (domain_num == 0) {
243 return {};
244 }
245
246 std::lock_guard lock{mutex_};
247
248 std::unique_ptr<ColumnValues> extra_column_values = extra_columns_.get_column_values(column_id);
249 if (extra_column_values) {
250 return extra_column_values;
251 }
252
253 if (component_->type() == bke::GeometryComponent::Type::Instance) {
254 if (const bke::Instances *instances =
255 static_cast<const bke::InstancesComponent &>(*component_).get())
256 {
257 if (STREQ(column_id.name, "Name")) {
258 Span<int> reference_handles = instances->reference_handles();
259 Span<bke::InstanceReference> references = instances->references();
260 return std::make_unique<ColumnValues>(
261 column_id.name,
263 domain_num, [reference_handles, references](int64_t index) {
264 return references[reference_handles[index]];
265 }));
266 }
267 Span<float4x4> transforms = instances->transforms();
268 if (STREQ(column_id.name, "Position")) {
269 return std::make_unique<ColumnValues>(
270 column_id.name, VArray<float3>::ForFunc(domain_num, [transforms](int64_t index) {
271 return transforms[index].location();
272 }));
273 }
274 if (STREQ(column_id.name, "Rotation")) {
275 return std::make_unique<ColumnValues>(
276 column_id.name, VArray<float3>::ForFunc(domain_num, [transforms](int64_t index) {
277 return float3(math::to_euler(math::normalize(transforms[index])));
278 }));
279 }
280 if (STREQ(column_id.name, "Scale")) {
281 return std::make_unique<ColumnValues>(
282 column_id.name, VArray<float3>::ForFunc(domain_num, [transforms](int64_t index) {
283 return math::to_scale<true>(transforms[index]);
284 }));
285 }
286 }
287 }
288 else if (component_->type() == bke::GeometryComponent::Type::GreasePencil) {
289 if (const GreasePencil *grease_pencil =
290 static_cast<const bke::GreasePencilComponent &>(*component_).get())
291 {
292 if (domain_ == bke::AttrDomain::Layer && STREQ(column_id.name, "Name")) {
293 const Span<const bke::greasepencil::Layer *> layers = grease_pencil->layers();
294 return std::make_unique<ColumnValues>(
295 column_id.name, VArray<std::string>::ForFunc(domain_num, [layers](int64_t index) {
296 StringRefNull name = layers[index]->name();
297 if (name.is_empty()) {
298 name = IFACE_("(Layer)");
299 }
300 return std::string(name);
301 }));
302 }
303 }
304 }
305 else if (G.debug_value == 4001 && component_->type() == bke::GeometryComponent::Type::Mesh) {
306 const bke::MeshComponent &component = static_cast<const bke::MeshComponent &>(*component_);
307 if (const Mesh *mesh = component.get()) {
308 if (std::unique_ptr<ColumnValues> values = build_mesh_debug_columns(
309 *mesh, domain_, column_id.name))
310 {
311 return values;
312 }
313 }
314 }
315
316 bke::GAttributeReader attribute = attributes->lookup(column_id.name);
317 if (!attribute) {
318 return {};
319 }
320 GVArray varray = std::move(attribute.varray);
321 if (attribute.domain != domain_) {
322 return {};
323 }
324
325 StringRefNull column_display_name = column_id.name;
326 if (column_display_name == ".viewer") {
327 column_display_name = "Viewer";
328 }
329
330 return std::make_unique<ColumnValues>(column_display_name, std::move(varray));
331}
332
333int GeometryDataSource::tot_rows() const
334{
335 std::optional<const bke::AttributeAccessor> attributes = this->get_component_attributes();
336 if (!attributes.has_value()) {
337 return {};
338 }
339 return attributes->domain_size(domain_);
340}
341
342bool GeometryDataSource::has_selection_filter() const
343{
344 if (!object_orig_) {
345 return false;
346 }
347 switch (component_->type()) {
349 if (object_orig_->type != OB_MESH) {
350 return false;
351 }
352 if (object_orig_->mode != OB_MODE_EDIT) {
353 return false;
354 }
355 return true;
356 }
358 if (object_orig_->type != OB_CURVES) {
359 return false;
360 }
361 if (!ELEM(object_orig_->mode, OB_MODE_SCULPT_CURVES, OB_MODE_EDIT)) {
362 return false;
363 }
364 return true;
365 }
367 if (object_orig_->type != OB_POINTCLOUD) {
368 return false;
369 }
370 if (object_orig_->mode != OB_MODE_EDIT) {
371 return false;
372 }
373 return true;
374 }
375 default:
376 return false;
377 }
378}
379
380IndexMask GeometryDataSource::apply_selection_filter(IndexMaskMemory &memory) const
381{
382 std::lock_guard lock{mutex_};
383 const IndexMask full_range(this->tot_rows());
384 if (full_range.is_empty()) {
385 return full_range;
386 }
387
388 switch (component_->type()) {
390 BLI_assert(object_orig_->type == OB_MESH);
391 BLI_assert(object_orig_->mode == OB_MODE_EDIT);
392 const Mesh *mesh_eval = geometry_set_.get_mesh();
393 const bke::AttributeAccessor attributes_eval = mesh_eval->attributes();
394 Mesh *mesh_orig = (Mesh *)object_orig_->data;
395 BMesh *bm = mesh_orig->runtime->edit_mesh->bm;
397
398 const int *orig_indices = (const int *)CustomData_get_layer(&mesh_eval->vert_data,
400 if (orig_indices != nullptr) {
401 /* Use CD_ORIGINDEX layer if it exists. */
402 VArray<bool> selection = attributes_eval.adapt_domain<bool>(
404 [bm, orig_indices](int vertex_index) -> bool {
405 const int i_orig = orig_indices[vertex_index];
406 if (i_orig < 0) {
407 return false;
408 }
409 if (i_orig >= bm->totvert) {
410 return false;
411 }
412 const BMVert *vert = BM_vert_at_index(bm, i_orig);
413 return BM_elem_flag_test(vert, BM_ELEM_SELECT);
414 }),
416 domain_);
417 return IndexMask::from_bools(selection, memory);
418 }
419
420 if (mesh_eval->verts_num == bm->totvert) {
421 /* Use a simple heuristic to match original vertices to evaluated ones. */
422 VArray<bool> selection = attributes_eval.adapt_domain<bool>(
423 VArray<bool>::ForFunc(mesh_eval->verts_num,
424 [bm](int vertex_index) -> bool {
425 const BMVert *vert = BM_vert_at_index(bm, vertex_index);
426 return BM_elem_flag_test(vert, BM_ELEM_SELECT);
427 }),
429 domain_);
430 return IndexMask::from_bools(selection, memory);
431 }
432
433 return full_range;
434 }
436 BLI_assert(object_orig_->type == OB_CURVES);
437 const bke::CurveComponent &component = static_cast<const bke::CurveComponent &>(*component_);
438 const Curves &curves_id = *component.get();
439 switch (domain_) {
441 return curves::retrieve_selected_points(curves_id, memory);
443 return curves::retrieve_selected_curves(curves_id, memory);
444 default:
446 }
447 return full_range;
448 }
450 BLI_assert(object_orig_->type == OB_POINTCLOUD);
451 const bke::AttributeAccessor attributes = *component_->attributes();
452 const VArray<bool> &selection = *attributes.lookup_or_default(
453 ".selection", bke::AttrDomain::Point, false);
454 return IndexMask::from_bools(selection, memory);
455 }
456 default:
457 return full_range;
458 }
459}
460
461std::optional<const bke::AttributeAccessor> GeometryDataSource::get_component_attributes() const
462{
463 if (component_->type() != bke::GeometryComponent::Type::GreasePencil) {
464 return component_->attributes();
465 }
466 const GreasePencil *grease_pencil = geometry_set_.get_grease_pencil();
467 if (!grease_pencil) {
468 return {};
469 }
470 if (domain_ == bke::AttrDomain::Layer) {
471 return grease_pencil->attributes();
472 }
473 if (layer_index_ >= 0 && layer_index_ < grease_pencil->layers().size()) {
474 if (const bke::greasepencil::Drawing *drawing = grease_pencil->get_eval_drawing(
475 grease_pencil->layer(layer_index_)))
476 {
477 return drawing->strokes().attributes();
478 }
479 }
480 return {};
481}
482
483void VolumeDataSource::foreach_default_column_ids(
484 FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const
485{
486 if (component_->is_empty()) {
487 return;
488 }
489
490 for (const char *name : {"Grid Name", "Data Type", "Class"}) {
491 SpreadsheetColumnID column_id{(char *)name};
492 fn(column_id, false);
493 }
494}
495
496std::unique_ptr<ColumnValues> VolumeDataSource::get_column_values(
497 const SpreadsheetColumnID &column_id) const
498{
499 const Volume *volume = component_->get();
500 if (volume == nullptr) {
501 return {};
502 }
503
504#ifdef WITH_OPENVDB
505 const int size = this->tot_rows();
506 if (STREQ(column_id.name, "Grid Name")) {
507 return std::make_unique<ColumnValues>(
508 IFACE_("Grid Name"), VArray<std::string>::ForFunc(size, [volume](int64_t index) {
509 const bke::VolumeGridData *volume_grid = BKE_volume_grid_get(volume, index);
510 return volume_grid->name();
511 }));
512 }
513 if (STREQ(column_id.name, "Data Type")) {
514 return std::make_unique<ColumnValues>(
515 IFACE_("Data Type"), VArray<std::string>::ForFunc(size, [volume](int64_t index) {
516 const bke::VolumeGridData *volume_grid = BKE_volume_grid_get(volume, index);
517 const VolumeGridType type = volume_grid->grid_type();
518 const char *name = nullptr;
520 return IFACE_(name);
521 }));
522 }
523 if (STREQ(column_id.name, "Class")) {
524 return std::make_unique<ColumnValues>(
525 IFACE_("Class"), VArray<std::string>::ForFunc(size, [volume](int64_t index) {
526 const bke::VolumeGridData *volume_grid = BKE_volume_grid_get(volume, index);
527 openvdb::GridClass grid_class = volume_grid->grid_class();
528 if (grid_class == openvdb::GridClass::GRID_FOG_VOLUME) {
529 return IFACE_("Fog Volume");
530 }
531 if (grid_class == openvdb::GridClass::GRID_LEVEL_SET) {
532 return IFACE_("Level Set");
533 }
534 return IFACE_("Unknown");
535 }));
536 }
537#else
538 UNUSED_VARS(column_id);
539#endif
540
541 return {};
542}
543
544int VolumeDataSource::tot_rows() const
545{
546 const Volume *volume = component_->get();
547 if (volume == nullptr) {
548 return 0;
549 }
550 return BKE_volume_num_grids(volume);
551}
552
554{
555 switch (reference.type()) {
557 const Object &object = reference.object();
558 return ED_outliner_icon_from_id(object.id);
559 }
561 return ICON_OUTLINER_COLLECTION;
562 }
564 return ICON_GEOMETRY_SET;
565 }
567 break;
568 }
569 }
570 return ICON_NONE;
571}
572
574 Object *object_eval)
575{
576 bke::GeometrySet geometry_set;
578 const Object *object_orig = DEG_get_original_object(object_eval);
579 if (object_orig->type == OB_MESH) {
580 const Mesh *mesh = static_cast<const Mesh *>(object_orig->data);
581 if (object_orig->mode == OB_MODE_EDIT) {
582 if (const BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
583 Mesh *new_mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
584 /* This is a potentially heavy operation to do on every redraw. The best solution here is
585 * to display the data directly from the bmesh without a conversion, which can be
586 * implemented a bit later. */
587 BM_mesh_bm_to_me_for_eval(*em->bm, *new_mesh, nullptr);
588 geometry_set.replace_mesh(new_mesh, bke::GeometryOwnershipType::Owned);
589 }
590 }
591 else {
592 geometry_set.replace_mesh(const_cast<Mesh *>(mesh), bke::GeometryOwnershipType::ReadOnly);
593 }
594 }
595 else if (object_orig->type == OB_POINTCLOUD) {
596 const PointCloud *pointcloud = static_cast<const PointCloud *>(object_orig->data);
597 geometry_set.replace_pointcloud(const_cast<PointCloud *>(pointcloud),
599 }
600 else if (object_orig->type == OB_CURVES) {
601 const Curves &curves_id = *static_cast<const Curves *>(object_orig->data);
602 geometry_set.replace_curves(&const_cast<Curves &>(curves_id),
604 }
605 else if (object_orig->type == OB_GREASE_PENCIL) {
606 const GreasePencil &grease_pencil = *static_cast<const GreasePencil *>(object_orig->data);
607 geometry_set.replace_grease_pencil(&const_cast<GreasePencil &>(grease_pencil),
609 }
610 }
611 else {
612 if (BLI_listbase_is_single(&sspreadsheet->viewer_path.path)) {
613 if (const bke::GeometrySet *geometry_eval = object_eval->runtime->geometry_set_eval) {
614 geometry_set = *geometry_eval;
615 }
616
617 if (object_eval->mode == OB_MODE_EDIT && object_eval->type == OB_MESH) {
621 }
622 }
623 }
624 else {
625 if (const ViewerNodeLog *viewer_log =
627 sspreadsheet->viewer_path))
628 {
629 geometry_set = viewer_log->geometry;
630 }
631 }
632 }
633 return geometry_set;
634}
635
637 const Span<SpreadsheetInstanceID> instance_ids)
638{
639 bke::GeometrySet geometry = root_geometry;
640 for (const SpreadsheetInstanceID &instance_id : instance_ids) {
641 const bke::Instances *instances = geometry.get_instances();
642 if (!instances) {
643 /* Return the best available geometry. */
644 return geometry;
645 }
646 const Span<bke::InstanceReference> references = instances->references();
647 if (instance_id.reference_index < 0 || instance_id.reference_index >= references.size()) {
648 /* Return the best available geometry. */
649 return geometry;
650 }
651 const bke::InstanceReference &reference = references[instance_id.reference_index];
652 bke::GeometrySet reference_geometry;
653 reference.to_geometry_set(reference_geometry);
654 geometry = reference_geometry;
655 }
656 return geometry;
657}
658
659std::unique_ptr<DataSource> data_source_from_geometry(const bContext *C, Object *object_eval)
660{
662
663 const bke::GeometrySet root_geometry_set = spreadsheet_get_display_geometry_set(sspreadsheet,
664 object_eval);
666 root_geometry_set, Span{sspreadsheet->instance_ids, sspreadsheet->instance_ids_num});
667
668 const bke::AttrDomain domain = (bke::AttrDomain)sspreadsheet->attribute_domain;
669 const auto component_type = bke::GeometryComponent::Type(sspreadsheet->geometry_component_type);
670 const int active_layer_index = sspreadsheet->active_layer_index;
671 if (!geometry_set.has(component_type)) {
672 return {};
673 }
674
675 if (component_type == bke::GeometryComponent::Type::Volume) {
676 return std::make_unique<VolumeDataSource>(std::move(geometry_set));
677 }
678 Object *object_orig = sspreadsheet->instance_ids_num == 0 ?
679 DEG_get_original_object(object_eval) :
680 nullptr;
681 return std::make_unique<GeometryDataSource>(
682 object_orig, std::move(geometry_set), component_type, domain, active_layer_index);
683}
684
685} // namespace blender::ed::spreadsheet
SpaceSpreadsheet * CTX_wm_space_spreadsheet(const bContext *C)
Low-level operations for curves.
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
Low-level operations for grease pencil.
void * BKE_id_new_nomain(short type, const char *name)
Definition lib_id.cc:1487
void BKE_mesh_wrapper_ensure_mdata(Mesh *mesh)
Mesh * BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval)
Volume data-block.
int BKE_volume_num_grids(const Volume *volume)
const blender::bke::VolumeGridData * BKE_volume_grid_get(const Volume *volume, int grid_index)
VolumeGridType
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
void void BLI_INLINE bool BLI_listbase_is_single(const struct ListBase *lb)
#define UNUSED_VARS(...)
#define ELEM(...)
#define STREQ(a, b)
#define IFACE_(msgid)
Object * DEG_get_original_object(Object *object)
ID and Library types, which are fundamental for SDNA.
@ ID_ME
@ OB_MODE_EDIT
@ OB_MODE_SCULPT_CURVES
@ OB_GREASE_PENCIL
@ OB_MESH
@ OB_POINTCLOUD
@ OB_CURVES
@ SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL
int ED_outliner_icon_from_id(const ID &id)
volatile int lock
@ BM_ELEM_SELECT
#define BM_elem_flag_test(ele, hflag)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
void BM_mesh_bm_to_me_for_eval(BMesh &bm, Mesh &mesh, const CustomData_MeshMasks *cd_mask_extra)
#define BM_VERT
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
AttributeSet attributes
static GVArray ForSpan(GSpan span)
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr const char * data() const
static VArray ForFunc(const int64_t size, GetFunc get_func)
GVArray adapt_domain(const GVArray &varray, const AttrDomain from_domain, const AttrDomain to_domain) const
std::unique_ptr< ColumnValues > get_column_values(const SpreadsheetColumnID &column_id) const
void foreach_default_column_ids(FunctionRef< void(const SpreadsheetColumnID &, bool is_extra)> fn) const
std::unique_ptr< ColumnValues > get_column_values(const SpreadsheetColumnID &column_id) const override
void foreach_default_column_ids(FunctionRef< void(const SpreadsheetColumnID &, bool is_extra)> fn) const override
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
static const ViewerNodeLog * find_viewer_node_log_for_path(const ViewerPath &viewer_path)
#define G(x, y, z)
bool attribute_name_is_anonymous(const StringRef name)
bool allow_procedural_attribute_access(StringRef attribute_name)
IndexMask retrieve_selected_curves(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
IndexMask retrieve_selected_points(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
bke::GeometrySet get_geometry_set_for_instance_ids(const bke::GeometrySet &root_geometry, const Span< SpreadsheetInstanceID > instance_ids)
bke::GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspreadsheet, Object *object_eval)
int get_instance_reference_icon(const bke::InstanceReference &reference)
std::unique_ptr< DataSource > data_source_from_geometry(const bContext *C, Object *object_eval)
static void add_mesh_debug_column_names(const Mesh &mesh, const bke::AttrDomain domain, FunctionRef< void(const SpreadsheetColumnID &, bool is_extra)> fn)
static std::unique_ptr< ColumnValues > build_mesh_debug_columns(const Mesh &mesh, const bke::AttrDomain domain, const StringRef name)
bool RNA_enum_name_from_value(const EnumPropertyItem *item, int value, const char **r_name)
const EnumPropertyItem rna_enum_volume_grid_data_type_items[]
Definition rna_volume.cc:27
__int64 int64_t
Definition stdint.h:89
int totvert
MeshRuntimeHandle * runtime
CustomData vert_data
int verts_num
ObjectRuntimeHandle * runtime
SpreadsheetInstanceID * instance_ids
uint8_t geometry_component_type
bool has(const GeometryComponent::Type component_type) const
void replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void replace_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void replace_grease_pencil(GreasePencil *grease_pencil, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)