Blender V4.5
spreadsheet_dataset_draw.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_listbase.h"
8#include "BLI_string.h"
9
10#include "DNA_curves_types.h"
11#include "DNA_mesh_types.h"
13#include "DNA_space_types.h"
15
16#include "BKE_context.hh"
17#include "BKE_curves.hh"
18#include "BKE_grease_pencil.hh"
19#include "BKE_instances.hh"
20#include "BKE_lib_id.hh"
21#include "BKE_volume.hh"
22
23#include "ED_spreadsheet.hh"
24#include "RNA_access.hh"
25#include "RNA_prototypes.hh"
26
27#include "UI_interface.hh"
28#include "UI_tree_view.hh"
29
30#include "WM_api.hh"
31#include "WM_types.hh"
32
33#include "BLT_translation.hh"
34
35#include "ED_outliner.hh"
36
39#include "spreadsheet_intern.hh"
40
42
45
48 std::optional<int> layer_index;
49 std::optional<bke::AttrDomain> domain;
50};
51
53{
54 /* Using the tree row button instead of a separate right aligned button gives padding
55 * to the right side of the number, which it didn't have with the button. */
56 UI_but_hint_drawstr_set(reinterpret_cast<uiBut *>(view_item.view_item_button()), str.c_str());
57}
58
59static void draw_count(ui::AbstractTreeViewItem &view_item, const int count)
60{
62 BLI_str_format_decimal_unit(element_count, count);
63 draw_row_suffix(view_item, element_count);
64}
65
67{
68 switch (domain) {
70 return IFACE_("Vertex");
72 return IFACE_("Edge");
74 return IFACE_("Face");
76 return IFACE_("Face Corner");
77 default:
79 return "";
80 }
81}
82
84{
85 switch (domain) {
87 return IFACE_("Control Point");
89 return IFACE_("Spline");
90 default:
92 return "";
93 }
94}
95
97{
98 switch (domain) {
100 return ICON_VERTEXSEL;
102 return ICON_EDGESEL;
104 return ICON_FACESEL;
106 return ICON_FACE_CORNER;
107 default:
109 return ICON_NONE;
110 }
111}
112
114{
115 switch (domain) {
117 return ICON_CURVE_BEZCIRCLE;
119 return ICON_CURVE_PATH;
120 default:
122 return ICON_NONE;
123 }
124}
125
127 public:
129
130 void get_parent_instance_ids(Vector<SpreadsheetInstanceID> &r_instance_ids) const;
131
132 void on_activate(bContext &C) override;
133
134 std::optional<bool> should_be_active() const override;
135};
136
138 public:
140 {
141 label_ = geometry.name.empty() ? IFACE_("(Geometry)") : geometry.name;
142 }
143
144 void build_row(uiLayout &row) override
145 {
146 row.label(label_, ICON_GEOMETRY_SET);
147 }
148};
149
151 private:
152 const bke::InstanceReference &reference_;
153 int reference_index_;
154 int user_count_;
155
156 public:
158 : reference_(instances.references()[reference_index]), reference_index_(reference_index)
159 {
160 label_ = std::to_string(reference_index);
161 user_count_ = instances.reference_user_counts()[reference_index];
162 }
163
164 void build_row(uiLayout &row) override
165 {
166 const int icon = get_instance_reference_icon(reference_);
167 StringRefNull name = reference_.name();
168 if (name.is_empty()) {
169 name = IFACE_("(Geometry)");
170 }
171 row.label(name, icon);
172 draw_count(*this, user_count_);
173 }
174
175 int reference_index() const
176 {
177 return reference_index_;
178 }
179};
180
182 private:
183 ResourceScope scope_;
184 bke::GeometrySet root_geometry_set_;
185 SpaceSpreadsheet &sspreadsheet_;
186 bScreen &screen_;
187
189
190 public:
192 : root_geometry_set_(std::move(geometry_set)),
193 sspreadsheet_(*CTX_wm_space_spreadsheet(&C)),
194 screen_(*CTX_wm_screen(&C))
195 {
196 }
197
198 void build_tree() override
199 {
200 auto &root_item = this->add_tree_item<RootGeometryViewItem>(root_geometry_set_);
201 root_item.uncollapse_by_default();
202 if (const bke::Instances *instances = root_geometry_set_.get_instances()) {
203 this->build_tree_for_instances(root_item, *instances);
204 }
205 }
206
208 {
209 const Span<bke::InstanceReference> references = instances.references();
210 for (const int reference_i : references.index_range()) {
211 auto &reference_item = parent.add_tree_item<InstanceReferenceViewItem>(instances,
212 reference_i);
213 const bke::InstanceReference &reference = references[reference_i];
214 bke::GeometrySet &reference_geometry = scope_.construct<bke::GeometrySet>();
215 reference.to_geometry_set(reference_geometry);
216 if (const bke::Instances *child_instances = reference_geometry.get_instances()) {
217 this->build_tree_for_instances(reference_item, *child_instances);
218 }
219 }
220 }
221};
222
224 public:
226
227 void on_activate(bContext &C) override;
228
229 std::optional<bool> should_be_active() const override;
230
232 virtual std::optional<GeometryDataIdentifier> get_geometry_data_id() const
233 {
234 return std::nullopt;
235 }
236};
237
239 private:
240 bool has_mesh_;
241
242 public:
243 MeshViewItem(const bool has_mesh) : has_mesh_(has_mesh)
244 {
245 label_ = IFACE_("Mesh");
246 }
247
248 void build_row(uiLayout &row) override
249 {
250 if (!has_mesh_) {
251 uiLayoutSetActive(&row, false);
252 }
253 row.label(label_, ICON_MESH_DATA);
254 }
255};
256
258 private:
259 const Mesh *mesh_;
260 bke::AttrDomain domain_;
261
262 public:
263 MeshDomainViewItem(const Mesh *mesh, const bke::AttrDomain domain) : mesh_(mesh), domain_(domain)
264 {
266 }
267
268 std::optional<GeometryDataIdentifier> get_geometry_data_id() const override
269 {
270 return GeometryDataIdentifier{bke::GeometryComponent::Type::Mesh, std::nullopt, domain_};
271 }
272
273 void build_row(uiLayout &row) override
274 {
275 const BIFIconID icon = mesh_domain_to_icon(domain_);
276 row.label(label_, icon);
277
278 const int count = mesh_ ? mesh_->attributes().domain_size(domain_) : 0;
279 draw_count(*this, count);
280 }
281};
282
284 private:
285 bool has_curves_;
286
287 public:
288 CurvesViewItem(const bool has_curves) : has_curves_(has_curves)
289 {
290 label_ = IFACE_("Curve");
291 }
292
293 void build_row(uiLayout &row) override
294 {
295 if (!has_curves_) {
296 uiLayoutSetActive(&row, false);
297 }
298 row.label(label_, ICON_CURVE_DATA);
299 }
300};
301
303 private:
304 const Curves *curves_;
305 bke::AttrDomain domain_;
306
307 public:
309 : curves_(curves), domain_(domain)
310 {
312 }
313
314 std::optional<GeometryDataIdentifier> get_geometry_data_id() const override
315 {
316 return GeometryDataIdentifier{bke::GeometryComponent::Type::Curve, std::nullopt, domain_};
317 }
318
319 void build_row(uiLayout &row) override
320 {
321 const BIFIconID icon = curves_domain_to_icon(domain_);
322 row.label(label_, icon);
323
324 const int count = curves_ ? curves_->geometry.wrap().attributes().domain_size(domain_) : 0;
325 draw_count(*this, count);
326 }
327};
328
330 bool has_grease_pencil_;
331
332 public:
333 GreasePencilViewItem(const bool has_grease_pencil) : has_grease_pencil_(has_grease_pencil)
334 {
335 label_ = IFACE_("Grease Pencil");
336 }
337
338 void build_row(uiLayout &row) override
339 {
340 if (!has_grease_pencil_) {
341 uiLayoutSetActive(&row, false);
342 }
343 row.label(label_, ICON_OUTLINER_DATA_GREASEPENCIL);
344 }
345};
346
348 private:
349 const GreasePencil *grease_pencil_;
350
351 public:
352 GreasePencilLayersViewItem(const GreasePencil *grease_pencil) : grease_pencil_(grease_pencil)
353 {
354 label_ = IFACE_("Layer");
355 }
356
357 std::optional<GeometryDataIdentifier> get_geometry_data_id() const override
358 {
361 }
362
363 void build_row(uiLayout &row) override
364 {
365 const int count = grease_pencil_ ? grease_pencil_->layers().size() : 0;
366 row.label(label_, ICON_OUTLINER_DATA_GP_LAYER);
367 draw_count(*this, count);
368 }
369};
370
372 private:
373 const bke::greasepencil::Layer &layer_;
374
375 public:
376 GreasePencilLayerViewItem(const GreasePencil &grease_pencil, const int layer_index)
377 : layer_(grease_pencil.layer(layer_index))
378 {
379 label_ = std::to_string(layer_index);
380 }
381
382 void build_row(uiLayout &row) override
383 {
384 StringRefNull name = layer_.name();
385 if (name.is_empty()) {
386 name = IFACE_("(Layer)");
387 }
388 row.label(name, ICON_CURVE_DATA);
389 }
390};
391
393 private:
394 const GreasePencil &grease_pencil_;
395 int layer_index_;
396 bke::AttrDomain domain_;
397
398 public:
400 const int layer_index,
401 const bke::AttrDomain domain)
402 : grease_pencil_(grease_pencil), layer_index_(layer_index), domain_(domain)
403 {
405 }
406
407 std::optional<GeometryDataIdentifier> get_geometry_data_id() const override
408 {
410 bke::GeometryComponent::Type::GreasePencil, layer_index_, domain_};
411 }
412
413 void build_row(uiLayout &row) override
414 {
415 const BIFIconID icon = curves_domain_to_icon(domain_);
416 row.label(label_, icon);
417
418 const bke::greasepencil::Drawing *drawing = grease_pencil_.get_eval_drawing(
419 grease_pencil_.layer(layer_index_));
420 const int count = drawing ? drawing->strokes().attributes().domain_size(domain_) : 0;
421 draw_count(*this, count);
422 }
423};
424
426 private:
427 bool has_pointcloud_;
428
429 public:
430 PointCloudViewItem(const bool has_pointcloud) : has_pointcloud_(has_pointcloud)
431 {
432 label_ = IFACE_("Point Cloud");
433 }
434
435 void build_row(uiLayout &row) override
436 {
437 if (!has_pointcloud_) {
438 uiLayoutSetActive(&row, false);
439 }
440 row.label(label_, ICON_POINTCLOUD_DATA);
441 }
442};
443
445 private:
446 const PointCloud *pointcloud_;
447
448 public:
450 {
451 label_ = IFACE_("Point");
452 }
453
454 std::optional<GeometryDataIdentifier> get_geometry_data_id() const override
455 {
458 }
459
460 void build_row(uiLayout &row) override
461 {
462 row.label(label_, ICON_POINTCLOUD_POINT);
463 const int count = pointcloud_ ? pointcloud_->totpoint : 0;
464 draw_count(*this, count);
465 }
466};
467
469 private:
470 const Volume *volume_;
471
472 public:
473 VolumeGridsViewItem(const Volume *volume) : volume_(volume)
474 {
475 label_ = IFACE_("Volume Grids");
476 }
477
478 std::optional<GeometryDataIdentifier> get_geometry_data_id() const override
479 {
481 bke::GeometryComponent::Type::Volume, std::nullopt, std::nullopt};
482 }
483
484 void build_row(uiLayout &row) override
485 {
486 if (!volume_) {
487 uiLayoutSetActive(&row, false);
488 }
489 row.label(label_, ICON_VOLUME_DATA);
490 if (volume_) {
491 draw_count(*this, BKE_volume_num_grids(volume_));
492 }
493 }
494};
495
497 private:
498 const bke::Instances *instances_;
499
500 public:
501 InstancesViewItem(const bke::Instances *instances) : instances_(instances)
502 {
503 label_ = IFACE_("Instances");
504 }
505
506 std::optional<GeometryDataIdentifier> get_geometry_data_id() const override
507 {
510 }
511
512 void build_row(uiLayout &row) override
513 {
514 if (!instances_) {
515 uiLayoutSetActive(&row, false);
516 }
517 row.label(label_, ICON_EMPTY_AXIS);
518 if (instances_) {
519 draw_count(*this, instances_->instances_num());
520 }
521 }
522};
523
525 private:
526 bke::GeometrySet geometry_set_;
527 SpaceSpreadsheet &sspreadsheet_;
528 bScreen &screen_;
529
530 friend class DataSetViewItem;
531
532 public:
534 : geometry_set_(std::move(geometry_set)),
535 sspreadsheet_(*CTX_wm_space_spreadsheet(&C)),
536 screen_(*CTX_wm_screen(&C))
537 {
538 }
539
540 void build_tree() override
541 {
542 this->build_tree_for_geometry(geometry_set_, *this);
543 }
544
546 {
547 const Mesh *mesh = geometry.get_mesh();
548 this->build_tree_for_mesh(mesh, parent);
549
550 const Curves *curves = geometry.get_curves();
551 this->build_tree_for_curves(curves, parent);
552
553 const GreasePencil *grease_pencil = geometry.get_grease_pencil();
554 this->build_tree_for_grease_pencil(grease_pencil, parent);
555
556 const PointCloud *pointcloud = geometry.get_pointcloud();
557 this->build_tree_for_pointcloud(pointcloud, parent);
558
559 const Volume *volume = geometry.get_volume();
560 this->build_tree_for_volume(volume, parent);
561
562 const bke::Instances *instances = geometry.get_instances();
563 this->build_tree_for_instances(instances, parent);
564 }
565
567 {
568 auto &mesh_item = parent.add_tree_item<MeshViewItem>(mesh != nullptr);
569 mesh_item.uncollapse_by_default();
570 if (!mesh) {
571 return;
572 }
573
574 mesh_item.add_tree_item<MeshDomainViewItem>(mesh, bke::AttrDomain::Point);
578 }
579
581 {
582 auto &curves_item = parent.add_tree_item<CurvesViewItem>(curves != nullptr);
583 curves_item.uncollapse_by_default();
584 if (!curves) {
585 return;
586 }
587
588 curves_item.add_tree_item<CurvesDomainViewItem>(curves, bke::AttrDomain::Point);
590 }
591
594 {
595 auto &grease_pencil_item = parent.add_tree_item<GreasePencilViewItem>(grease_pencil !=
596 nullptr);
597 grease_pencil_item.uncollapse_by_default();
598 if (!grease_pencil) {
599 return;
600 }
601
602 auto &layers_item = grease_pencil_item.add_tree_item<GreasePencilLayersViewItem>(
603 grease_pencil);
604 const Span<const bke::greasepencil::Layer *> layers = grease_pencil->layers();
605 for (const int layer_i : layers.index_range()) {
606 auto &layer_item = layers_item.add_tree_item<GreasePencilLayerViewItem>(*grease_pencil,
607 layer_i);
609 *grease_pencil, layer_i, bke::AttrDomain::Point);
611 *grease_pencil, layer_i, bke::AttrDomain::Curve);
612 }
613 }
614
616 {
617 auto &pointcloud_item = parent.add_tree_item<PointCloudViewItem>(pointcloud != nullptr);
618 pointcloud_item.uncollapse_by_default();
619 if (!pointcloud) {
620 return;
621 }
622
623 pointcloud_item.add_tree_item<PointsViewItem>(pointcloud);
624 }
625
627 {
628 parent.add_tree_item<VolumeGridsViewItem>(volume);
629 }
630
632 {
633 parent.add_tree_item<InstancesViewItem>(instances);
634 }
635};
636
638{
639 return static_cast<GeometryDataSetTreeView &>(this->get_tree_view());
640}
641
646
648 Vector<SpreadsheetInstanceID> &r_instance_ids) const
649{
650 if (const auto *reference_item = dynamic_cast<const InstanceReferenceViewItem *>(this)) {
651 r_instance_ids.append({reference_item->reference_index()});
652 }
653 this->foreach_parent([&](const ui::AbstractTreeViewItem &item) {
654 if (const auto *reference_item = dynamic_cast<const InstanceReferenceViewItem *>(&item)) {
655 r_instance_ids.append({reference_item->reference_index()});
656 }
657 });
658 std::reverse(r_instance_ids.begin(), r_instance_ids.end());
659}
660
662{
663 GeometryInstancesTreeView &tree_view = this->get_tree();
664 SpaceSpreadsheet &sspreadsheet = tree_view.sspreadsheet_;
665
667 this->get_parent_instance_ids(instance_ids);
668 if (sspreadsheet.geometry_id.instance_ids_num != instance_ids.size()) {
669 return false;
670 }
671 for (const int i : instance_ids.index_range()) {
672 const SpreadsheetInstanceID &a = sspreadsheet.geometry_id.instance_ids[i];
673 const SpreadsheetInstanceID &b = instance_ids[i];
674 if (a.reference_index != b.reference_index) {
675 return false;
676 }
677 }
678 return true;
679}
680
682{
684 this->get_parent_instance_ids(instance_ids);
685
687
690 instance_ids.size(), __func__);
691 sspreadsheet.geometry_id.instance_ids_num = instance_ids.size();
693 instance_ids.data(), instance_ids.size(), sspreadsheet.geometry_id.instance_ids);
694
696}
697
699{
700 std::optional<GeometryDataIdentifier> data_id = this->get_geometry_data_id();
701 if (!data_id) {
702 this->foreach_item_recursive([&](const ui::AbstractTreeViewItem &item) {
703 if (data_id) {
704 return;
705 }
706 if (const auto *data_set_view_item = dynamic_cast<const DataSetViewItem *>(&item)) {
707 data_id = data_set_view_item->get_geometry_data_id();
708 }
709 });
710 if (!data_id) {
711 return;
712 }
713 }
714
715 bScreen &screen = *CTX_wm_screen(&C);
717
718 sspreadsheet.geometry_id.geometry_component_type = uint8_t(data_id->component_type);
719 if (data_id->domain) {
720 sspreadsheet.geometry_id.attribute_domain = uint8_t(*data_id->domain);
721 }
722 if (data_id->layer_index) {
723 sspreadsheet.geometry_id.layer_index = *data_id->layer_index;
724 }
725 PointerRNA ptr = RNA_pointer_create_discrete(&screen.id, &RNA_SpaceSpreadsheet, &sspreadsheet);
726 /* These updates also make sure that the attribute domain is set properly based on the
727 * component type. */
728 RNA_property_update(&C, &ptr, RNA_struct_find_property(&ptr, "attribute_domain"));
729 RNA_property_update(&C, &ptr, RNA_struct_find_property(&ptr, "geometry_component_type"));
730}
731
732std::optional<bool> DataSetViewItem::should_be_active() const
733{
734 GeometryDataSetTreeView &tree_view = this->get_tree();
735 SpaceSpreadsheet &sspreadsheet = tree_view.sspreadsheet_;
736
737 const std::optional<GeometryDataIdentifier> data_id = this->get_geometry_data_id();
738 if (!data_id) {
739 return false;
740 }
742 data_id->component_type)
743 {
744 return false;
745 }
746 if (data_id->domain) {
747 if (bke::AttrDomain(sspreadsheet.geometry_id.attribute_domain) != data_id->domain) {
748 return false;
749 }
750 }
751 if (data_id->layer_index) {
752 if (sspreadsheet.geometry_id.layer_index != *data_id->layer_index) {
753 return false;
754 }
755 }
756 return true;
757}
758
760 private:
761 int viewer_path_index_;
762
763 public:
764 ViewerPathTreeViewItem(int viewer_path_index) : viewer_path_index_(viewer_path_index) {}
765
766 void on_activate(bContext &C) override;
767 std::optional<bool> should_be_active() const override;
768};
769
771 const IDViewerPathElem &id_elem_;
772
773 public:
774 IDViewerPathItem(const int viewer_path_index, const IDViewerPathElem &id_elem)
775 : ViewerPathTreeViewItem(viewer_path_index), id_elem_(id_elem)
776 {
777 label_ = id_elem.id ? id_elem.id->name + 2 : IFACE_("No Data-Block");
778 }
779
780 void build_row(uiLayout &row) override
781 {
782 if (id_elem_.id) {
783 const int icon = ED_outliner_icon_from_id(*id_elem_.id);
784 row.label(BKE_id_name(*id_elem_.id), icon);
785 }
786 else {
787 row.label(IFACE_("No Data-Block"), ICON_BLANK1);
788 }
789 }
790};
791
793 const ModifierViewerPathElem &modifier_elem_;
794
795 public:
796 ModifierViewerPathItem(const int viewer_path_index, const ModifierViewerPathElem &modifier_elem)
797 : ViewerPathTreeViewItem(viewer_path_index), modifier_elem_(modifier_elem)
798 {
799 label_ = modifier_elem.base.ui_name;
800 }
801
802 void build_row(uiLayout &row) override
803 {
804 row.label(modifier_elem_.base.ui_name, ICON_MODIFIER);
805 }
806};
807
809 const GroupNodeViewerPathElem &group_node_elem_;
810
811 public:
812 GroupNodeViewerPathItem(const int viewer_path_index,
813 const GroupNodeViewerPathElem &group_node_elem)
814 : ViewerPathTreeViewItem(viewer_path_index), group_node_elem_(group_node_elem)
815 {
816 label_ = group_node_elem.base.ui_name;
817 }
818
819 void build_row(uiLayout &row) override
820 {
821 row.label(group_node_elem_.base.ui_name, ICON_NODE);
822 }
823};
824
826 const ViewerNodeViewerPathElem &viewer_node_elem_;
827
828 public:
829 ViewerNodeViewerPathItem(const int viewer_path_index,
830 const ViewerNodeViewerPathElem &viewer_node_elem)
831 : ViewerPathTreeViewItem(viewer_path_index), viewer_node_elem_(viewer_node_elem)
832 {
833 label_ = viewer_node_elem.base.ui_name;
834 }
835
836 void build_row(uiLayout &row) override
837 {
838 row.label(viewer_node_elem_.base.ui_name, ICON_RESTRICT_VIEW_OFF);
839 }
840};
841
843
844 public:
845 SimulationViewerPathPathItem(const int viewer_path_index,
846 const SimulationZoneViewerPathElem & /*simulation_zone_elem*/)
847 : ViewerPathTreeViewItem(viewer_path_index)
848 {
849 label_ = IFACE_("Simulation");
850 }
851
852 void build_row(uiLayout &row) override
853 {
854 row.label(label_, ICON_BLANK1);
855 }
856};
857
859 private:
860 const RepeatZoneViewerPathElem &repeat_zone_;
861
862 public:
863 RepeatViewerPathItem(const int viewer_path_index, const RepeatZoneViewerPathElem &repeat_zone)
864 : ViewerPathTreeViewItem(viewer_path_index), repeat_zone_(repeat_zone)
865 {
866 label_ = IFACE_("Repeat");
867 }
868
869 void build_row(uiLayout &row) override
870 {
871 row.label(label_, ICON_BLANK1);
872 draw_row_suffix(*this, std::to_string(repeat_zone_.iteration));
873 }
874};
875
877 private:
878 const ForeachGeometryElementZoneViewerPathElem &foreach_geo_elem_zone_;
879
880 public:
882 const int viewer_path_index,
883 const ForeachGeometryElementZoneViewerPathElem &foreach_geo_elem_zone)
884 : ViewerPathTreeViewItem(viewer_path_index), foreach_geo_elem_zone_(foreach_geo_elem_zone)
885 {
886 label_ = IFACE_("For Each Element");
887 }
888
889 void build_row(uiLayout &row) override
890 {
891 row.label(label_, ICON_BLANK1);
892 draw_row_suffix(*this, std::to_string(foreach_geo_elem_zone_.index));
893 }
894};
895
897 public:
898 EvaluteClosureViewerPathItem(const int viewer_path_index,
899 const EvaluateClosureNodeViewerPathElem & /*evalute_closure_elem*/)
900 : ViewerPathTreeViewItem(viewer_path_index)
901 {
902 label_ = IFACE_("Evaluate Closure");
903 }
904
905 void build_row(uiLayout &row) override
906 {
907 row.label(label_, ICON_BLANK1);
908 }
909};
910
912 private:
913 SpaceSpreadsheet &sspreadsheet_;
914 bScreen &screen_;
915
916 friend ViewerPathTreeViewItem;
917
918 public:
920 : sspreadsheet_(*CTX_wm_space_spreadsheet(&C)), screen_(*CTX_wm_screen(&C))
921 {
922 /* This tree view contains only a flat list of items without. */
923 is_flat_ = true;
924 }
925
926 void build_tree() override
927 {
928 const ViewerPath &viewer_path = sspreadsheet_.geometry_id.viewer_path;
929
930 int index;
931 LISTBASE_FOREACH_INDEX (const ViewerPathElem *, elem, &viewer_path.path, index) {
932 if (elem == viewer_path.path.first) {
933 /* The root item is drawn above the tree view already. */
934 continue;
935 }
936 this->add_viewer_path_elem(index, *elem);
937 }
938 }
939
940 void add_viewer_path_elem(const int index, const ViewerPathElem &elem)
941 {
942 switch (ViewerPathElemType(elem.type)) {
945 reinterpret_cast<const IDViewerPathElem &>(elem));
946 break;
947 }
950 index, reinterpret_cast<const ModifierViewerPathElem &>(elem));
951 break;
952 }
955 index, reinterpret_cast<const GroupNodeViewerPathElem &>(elem));
956 break;
957 }
960 index, reinterpret_cast<const ViewerNodeViewerPathElem &>(elem));
961 break;
962 }
965 index, reinterpret_cast<const SimulationZoneViewerPathElem &>(elem));
966 break;
967 }
970 index, reinterpret_cast<const RepeatZoneViewerPathElem &>(elem));
971 break;
972 }
975 index, reinterpret_cast<const ForeachGeometryElementZoneViewerPathElem &>(elem));
976 break;
977 }
980 index, reinterpret_cast<const EvaluateClosureNodeViewerPathElem &>(elem));
981 break;
982 }
983 }
984 }
985};
986
993
995{
996 /* Can use SpaceSpreadsheet.active_viewer_path_index once selection is used. */
997 return false;
998}
999
1001{
1002 layout.label(IFACE_("No Active Context"), ICON_NONE);
1003}
1004
1006{
1008 return false;
1009 }
1010 const ViewerPathElem &last_elem = *static_cast<const ViewerPathElem *>(viewer_path.path.last);
1012}
1013
1014static void draw_viewer_path_panel(const bContext &C, uiLayout &layout)
1015{
1016 uiBlock *block = uiLayoutGetBlock(&layout);
1018 *block, "Viewer Path", std::make_unique<ViewerPathTreeView>(C));
1019 tree_view->set_context_menu_title("Viewer Path");
1020 ui::TreeViewBuilder::build_tree_view(C, *tree_view, layout, {}, true);
1021}
1022
1023static void draw_context_panel_content(const bContext &C, uiLayout &layout)
1024{
1025 bScreen &screen = *CTX_wm_screen(&C);
1027
1029 ID *root_id = get_current_id(sspreadsheet);
1030 if (!root_id) {
1032 return;
1033 }
1034 if (GS(root_id->name) != ID_OB) {
1036 return;
1037 }
1038
1039 PointerRNA sspreadsheet_ptr = RNA_pointer_create_discrete(
1040 &screen.id, &RNA_SpaceSpreadsheet, sspreadsheet);
1041
1042 layout.prop(&sspreadsheet_ptr, "object_eval_state", UI_ITEM_NONE, "", ICON_NONE);
1043
1046 {
1047 if (uiLayout *panel = layout.panel(&C, "viewer path", true, IFACE_("Viewer Path"))) {
1048 draw_viewer_path_panel(C, *panel);
1049 }
1050 }
1051}
1052
1053static void draw_context_panel(const bContext &C, uiLayout &layout)
1054{
1055 SpaceSpreadsheet &sspreadsheet = *CTX_wm_space_spreadsheet(&C);
1056
1057 PanelLayout context_panel = layout.panel(&C, "context", false);
1059 if (ID *root_id = get_current_id(&sspreadsheet)) {
1060 std::string label = BKE_id_name(*root_id);
1061 if (!context_panel.body) {
1062 switch (sspreadsheet.geometry_id.object_eval_state) {
1064 label += " (Evaluated)";
1065 break;
1067 label += " (Original)";
1068 break;
1070 label += " (Viewer)";
1071 break;
1072 }
1073 }
1074 context_panel.header->label(label, ICON_OBJECT_DATA);
1075 }
1076 else {
1077 context_panel.header->label(IFACE_("Context"), ICON_NONE);
1078 }
1079 context_panel.header->op("spreadsheet.toggle_pin",
1080 "",
1081 sspreadsheet.flag & SPREADSHEET_FLAG_PINNED ? ICON_PINNED :
1082 ICON_UNPINNED);
1083 if (context_panel.body) {
1084 draw_context_panel_content(C, *context_panel.body);
1085 }
1086}
1087
1089{
1091
1092 uiLayout *layout = panel->layout;
1093 uiBlock *block = uiLayoutGetBlock(layout);
1094 UI_block_layout_set_current(block, layout);
1095
1096 draw_context_panel(*C, *layout);
1097
1099 if (!object) {
1100 return;
1101 }
1102
1103 const bke::GeometrySet root_geometry = spreadsheet_get_display_geometry_set(sspreadsheet,
1104 object);
1105
1106 if (uiLayout *panel = layout->panel(C, "instance tree", false, IFACE_("Geometry"))) {
1108 *block,
1109 "Instances Tree View",
1110 std::make_unique<GeometryInstancesTreeView>(root_geometry, *C));
1111 tree_view->set_context_menu_title("Instance");
1112 ui::TreeViewBuilder::build_tree_view(*C, *tree_view, *panel, {}, false);
1113 }
1114 if (uiLayout *panel = layout->panel(C, "geometry_domain_tree_view", false, IFACE_("Domain"))) {
1116 root_geometry,
1117 {sspreadsheet->geometry_id.instance_ids, sspreadsheet->geometry_id.instance_ids_num});
1119 *block,
1120 "Data Set Tree View",
1121 std::make_unique<GeometryDataSetTreeView>(std::move(instance_geometry), *C));
1122 tree_view->set_context_menu_title("Domain");
1123 ui::TreeViewBuilder::build_tree_view(*C, *tree_view, *panel, {}, false);
1124 }
1125}
1126
1127} // namespace blender::ed::spreadsheet
bScreen * CTX_wm_screen(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
SpaceSpreadsheet * CTX_wm_space_spreadsheet(const bContext *C)
Low-level operations for curves.
Low-level operations for grease pencil.
const char * BKE_id_name(const ID &id)
Volume data-block.
int BKE_volume_num_grids(const Volume *volume)
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
#define BLI_STR_FORMAT_INT32_DECIMAL_UNIT_SIZE
Definition BLI_string.h:34
void BLI_str_format_decimal_unit(char dst[BLI_STR_FORMAT_INT32_DECIMAL_UNIT_SIZE], int number_to_format) ATTR_NONNULL(1)
Definition string.cc:1268
#define IFACE_(msgid)
@ ID_OB
@ SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE
@ SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED
@ SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL
@ SPREADSHEET_FLAG_PINNED
@ VIEWER_PATH_ELEM_TYPE_GROUP_NODE
@ VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE
@ VIEWER_PATH_ELEM_TYPE_FOREACH_GEOMETRY_ELEMENT_ZONE
@ VIEWER_PATH_ELEM_TYPE_VIEWER_NODE
@ VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE
@ VIEWER_PATH_ELEM_TYPE_MODIFIER
@ VIEWER_PATH_ELEM_TYPE_EVALUATE_CLOSURE
@ VIEWER_PATH_ELEM_TYPE_ID
int BIFIconID
Definition ED_asset.hh:29
int ED_outliner_icon_from_id(const ID &id)
#define C
Definition RandGen.cpp:29
blender::ui::AbstractGridView * UI_block_add_view(uiBlock &block, blender::StringRef idname, std::unique_ptr< blender::ui::AbstractGridView > grid_view)
void UI_but_hint_drawstr_set(uiBut *but, const char *string)
void uiLayoutSetActive(uiLayout *layout, bool active)
uiBlock * uiLayoutGetBlock(uiLayout *layout)
#define UI_ITEM_NONE
void uiLayoutSetEmboss(uiLayout *layout, blender::ui::EmbossType emboss)
void UI_block_layout_set_current(uiBlock *block, uiLayout *layout)
#define ND_SPACE_SPREADSHEET
Definition WM_types.hh:538
#define NC_SPACE
Definition WM_types.hh:389
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
constexpr bool is_empty() const
int64_t size() const
void append(const T &value)
IndexRange index_range() const
int domain_size(const AttrDomain domain) const
AttributeAccessor attributes() const
Span< InstanceReference > references() const
Definition instances.cc:285
Span< int > reference_user_counts() const
Definition instances.cc:488
const bke::CurvesGeometry & strokes() const
CurvesDomainViewItem(const Curves *curves, const bke::AttrDomain domain)
std::optional< GeometryDataIdentifier > get_geometry_data_id() const override
virtual std::optional< GeometryDataIdentifier > get_geometry_data_id() const
std::optional< bool > should_be_active() const override
EvaluteClosureViewerPathItem(const int viewer_path_index, const EvaluateClosureNodeViewerPathElem &)
ForeachElementViewerPathItem(const int viewer_path_index, const ForeachGeometryElementZoneViewerPathElem &foreach_geo_elem_zone)
void build_tree_for_pointcloud(const PointCloud *pointcloud, ui::TreeViewItemContainer &parent)
void build_tree_for_grease_pencil(const GreasePencil *grease_pencil, ui::TreeViewItemContainer &parent)
GeometryDataSetTreeView(bke::GeometrySet geometry_set, const bContext &C)
void build_tree_for_instances(const bke::Instances *instances, ui::TreeViewItemContainer &parent)
void build_tree_for_curves(const Curves *curves, ui::TreeViewItemContainer &parent)
void build_tree_for_volume(const Volume *volume, ui::TreeViewItemContainer &parent)
void build_tree_for_mesh(const Mesh *mesh, ui::TreeViewItemContainer &parent)
void build_tree_for_geometry(const bke::GeometrySet &geometry, ui::TreeViewItemContainer &parent)
GeometryInstancesTreeView(bke::GeometrySet geometry_set, const bContext &C)
void build_tree_for_instances(ui::TreeViewItemContainer &parent, const bke::Instances &instances)
GreasePencilLayerCurvesDomainViewItem(const GreasePencil &grease_pencil, const int layer_index, const bke::AttrDomain domain)
std::optional< GeometryDataIdentifier > get_geometry_data_id() const override
GreasePencilLayerViewItem(const GreasePencil &grease_pencil, const int layer_index)
std::optional< GeometryDataIdentifier > get_geometry_data_id() const override
GroupNodeViewerPathItem(const int viewer_path_index, const GroupNodeViewerPathElem &group_node_elem)
IDViewerPathItem(const int viewer_path_index, const IDViewerPathElem &id_elem)
InstanceReferenceViewItem(const bke::Instances &instances, const int reference_index)
void get_parent_instance_ids(Vector< SpreadsheetInstanceID > &r_instance_ids) const
std::optional< bool > should_be_active() const override
std::optional< GeometryDataIdentifier > get_geometry_data_id() const override
std::optional< GeometryDataIdentifier > get_geometry_data_id() const override
MeshDomainViewItem(const Mesh *mesh, const bke::AttrDomain domain)
ModifierViewerPathItem(const int viewer_path_index, const ModifierViewerPathElem &modifier_elem)
std::optional< GeometryDataIdentifier > get_geometry_data_id() const override
RepeatViewerPathItem(const int viewer_path_index, const RepeatZoneViewerPathElem &repeat_zone)
SimulationViewerPathPathItem(const int viewer_path_index, const SimulationZoneViewerPathElem &)
ViewerNodeViewerPathItem(const int viewer_path_index, const ViewerNodeViewerPathElem &viewer_node_elem)
std::optional< bool > should_be_active() const override
void add_viewer_path_elem(const int index, const ViewerPathElem &elem)
std::optional< GeometryDataIdentifier > get_geometry_data_id() const override
Abstract base class for defining a customizable tree-view item.
AbstractTreeView & get_tree_view() const
Definition tree_view.cc:620
uiButViewItem * view_item_button() const
void set_context_menu_title(const std::string &title)
static void build_tree_view(const bContext &C, AbstractTreeView &tree_view, uiLayout &layout, std::optional< StringRef > search_string={}, bool add_box=true)
Definition tree_view.cc:980
ItemT & add_tree_item(Args &&...args)
void foreach_item_recursive(ItemIterFn iter_fn, IterOptions options=IterOptions::None) const
Definition tree_view.cc:72
void foreach_parent(ItemIterFn iter_fn) const
Definition tree_view.cc:92
#define str(s)
#define MEM_SAFE_FREE(v)
#define GS(a)
int count
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
static StringRefNull mesh_domain_to_label(const bke::AttrDomain domain)
static void draw_count(ui::AbstractTreeViewItem &view_item, const int count)
void spreadsheet_data_set_panel_draw(const bContext *C, Panel *panel)
static StringRefNull curves_domain_to_label(const bke::AttrDomain domain)
bke::GeometrySet get_geometry_set_for_instance_ids(const bke::GeometrySet &root_geometry, const Span< SpreadsheetInstanceID > instance_ids)
static void draw_viewer_path_panel(const bContext &C, uiLayout &layout)
bke::GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspreadsheet, Object *object_eval)
static void draw_row_suffix(ui::AbstractTreeViewItem &view_item, const StringRefNull str)
int get_instance_reference_icon(const bke::InstanceReference &reference)
Object * spreadsheet_get_object_eval(const SpaceSpreadsheet *sspreadsheet, const Depsgraph *depsgraph)
ID * get_current_id(const SpaceSpreadsheet *sspreadsheet)
static bool viewer_path_ends_with_viewer_node(const ViewerPath &viewer_path)
static void draw_context_panel_content(const bContext &C, uiLayout &layout)
static void draw_context_panel_without_context(uiLayout &layout)
static BIFIconID curves_domain_to_icon(const bke::AttrDomain domain)
static BIFIconID mesh_domain_to_icon(const bke::AttrDomain domain)
static void draw_context_panel(const bContext &C, uiLayout &layout)
void initialized_copy_n(const T *src, int64_t n, T *dst)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
Definition DNA_ID.h:404
char name[66]
Definition DNA_ID.h:415
struct uiLayout * layout
SpreadsheetTableIDGeometry geometry_id
SpreadsheetInstanceID * instance_ids
const Instances * get_instances() const
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, wmOperatorCallContext context, eUI_Item_Flag flag)
PanelLayout panel(const bContext *C, blender::StringRef idname, bool default_closed)
void label(blender::StringRef name, int icon)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
i
Definition text_draw.cc:230
void WM_main_add_notifier(uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4226