diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc index 74f20e58e5d..83dbd8f9727 100644 --- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc +++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc @@ -513,6 +513,10 @@ static void spreadsheet_main_region_listener(const wmRegionListenerParams *param ED_region_tag_redraw(region); break; } + case NC_GPENCIL: { + ED_region_tag_redraw(region); + break; + } case NC_VIEWER_PATH: { if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) { ED_region_tag_redraw(region); @@ -566,6 +570,10 @@ static void spreadsheet_header_region_listener(const wmRegionListenerParams *par ED_region_tag_redraw(region); break; } + case NC_GPENCIL: { + ED_region_tag_redraw(region); + break; + } case NC_VIEWER_PATH: { if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE) { ED_region_tag_redraw(region); diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index 406cb8f6841..67b094ebbc8 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -11,7 +11,9 @@ #include "BKE_curves.hh" #include "BKE_editmesh.h" #include "BKE_geometry_fields.hh" +#include "BKE_geometry_set.hh" #include "BKE_global.h" +#include "BKE_grease_pencil.hh" #include "BKE_instances.hh" #include "BKE_lib_id.h" #include "BKE_mesh.hh" @@ -173,12 +175,11 @@ static std::unique_ptr build_mesh_debug_columns(const Mesh &mesh, void GeometryDataSource::foreach_default_column_ids( FunctionRef fn) const { - if (!component_->attributes().has_value()) { + std::optional attributes = this->get_component_attributes(); + if (!attributes.has_value()) { return; } - const bke::AttributeAccessor attributes = *component_->attributes(); - - if (attributes.domain_size(domain_) == 0) { + if (attributes->domain_size(domain_) == 0) { return; } @@ -186,9 +187,13 @@ void GeometryDataSource::foreach_default_column_ids( fn({(char *)"Name"}, false); } + if (component_->type() == bke::GeometryComponent::Type::GreasePencil) { + fn({(char *)"Name"}, false); + } + extra_columns_.foreach_default_column_ids(fn); - attributes.for_all( + attributes->for_all( [&](const bke::AttributeIDRef &attribute_id, const bke::AttributeMetaData &meta_data) { if (meta_data.domain != domain_) { return true; @@ -221,11 +226,11 @@ void GeometryDataSource::foreach_default_column_ids( std::unique_ptr GeometryDataSource::get_column_values( const SpreadsheetColumnID &column_id) const { - if (!component_->attributes().has_value()) { + std::optional attributes = this->get_component_attributes(); + if (!attributes.has_value()) { return {}; } - const bke::AttributeAccessor attributes = *component_->attributes(); - const int domain_num = attributes.domain_size(domain_); + const int domain_num = attributes->domain_size(domain_); if (domain_num == 0) { return {}; } @@ -266,6 +271,19 @@ std::unique_ptr GeometryDataSource::get_column_values( } } } + else if (component_->type() == bke::GeometryComponent::Type::GreasePencil) { + if (const GreasePencil *grease_pencil = + static_cast(*component_).get()) + { + if (domain_ == ATTR_DOMAIN_LAYER && STREQ(column_id.name, "Name")) { + const Span layers = grease_pencil->layers(); + return std::make_unique( + column_id.name, VArray::ForFunc(domain_num, [layers](int64_t index) { + return std::string(layers[index]->name()); + })); + } + } + } else if (G.debug_value == 4001 && component_->type() == bke::GeometryComponent::Type::Mesh) { const bke::MeshComponent &component = static_cast(*component_); if (const Mesh *mesh = component.get()) { @@ -277,7 +295,7 @@ std::unique_ptr GeometryDataSource::get_column_values( } } - bke::GAttributeReader attribute = attributes.lookup(column_id.name); + bke::GAttributeReader attribute = attributes->lookup(column_id.name); if (!attribute) { return {}; } @@ -296,11 +314,11 @@ std::unique_ptr GeometryDataSource::get_column_values( int GeometryDataSource::tot_rows() const { - if (!component_->attributes().has_value()) { + std::optional attributes = this->get_component_attributes(); + if (!attributes.has_value()) { return {}; } - const bke::AttributeAccessor attributes = *component_->attributes(); - return attributes.domain_size(domain_); + return attributes->domain_size(domain_); } bool GeometryDataSource::has_selection_filter() const @@ -421,6 +439,28 @@ IndexMask GeometryDataSource::apply_selection_filter(IndexMaskMemory &memory) co } } +std::optional GeometryDataSource::get_component_attributes() const +{ + if (component_->type() != bke::GeometryComponent::Type::GreasePencil) { + return component_->attributes(); + } + const GreasePencil *grease_pencil = geometry_set_.get_grease_pencil(); + if (!grease_pencil) { + return {}; + } + if (domain_ == ATTR_DOMAIN_LAYER) { + return grease_pencil->attributes(); + } + if (layer_index_ >= 0 && layer_index_ < grease_pencil->layers().size()) { + if (const bke::greasepencil::Drawing *drawing = + bke::greasepencil::get_eval_grease_pencil_layer_drawing(*grease_pencil, layer_index_)) + { + return drawing->strokes().attributes(); + } + } + return {}; +} + void VolumeDataSource::foreach_default_column_ids( FunctionRef fn) const { @@ -524,6 +564,11 @@ bke::GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *ss geometry_set.replace_curves(&const_cast(curves_id), bke::GeometryOwnershipType::ReadOnly); } + else if (object_orig->type == OB_GREASE_PENCIL) { + const GreasePencil &grease_pencil = *static_cast(object_orig->data); + geometry_set.replace_grease_pencil(&const_cast(grease_pencil), + bke::GeometryOwnershipType::ReadOnly); + } } else { if (BLI_listbase_is_single(&sspreadsheet->viewer_path.path)) { @@ -555,6 +600,7 @@ std::unique_ptr data_source_from_geometry(const bContext *C, Object SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C); const eAttrDomain domain = (eAttrDomain)sspreadsheet->attribute_domain; const auto component_type = bke::GeometryComponent::Type(sspreadsheet->geometry_component_type); + const int active_layer_index = sspreadsheet->active_layer_index; bke::GeometrySet geometry_set = spreadsheet_get_display_geometry_set(sspreadsheet, object_eval); if (!geometry_set.has(component_type)) { return {}; @@ -564,7 +610,7 @@ std::unique_ptr data_source_from_geometry(const bContext *C, Object return std::make_unique(std::move(geometry_set)); } return std::make_unique( - object_eval, std::move(geometry_set), component_type, domain); + object_eval, std::move(geometry_set), component_type, domain, active_layer_index); } } // namespace blender::ed::spreadsheet diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh index 53f18a679e0..dfc7f5429eb 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh @@ -43,6 +43,8 @@ class GeometryDataSource : public DataSource { const bke::GeometrySet geometry_set_; const bke::GeometryComponent *component_; eAttrDomain domain_; + /* Layer index for grease pencil component. */ + int layer_index_; ExtraColumns extra_columns_; /* Some data is computed on the fly only when it is requested. Computing it does not change the @@ -56,11 +58,13 @@ class GeometryDataSource : public DataSource { bke::GeometrySet geometry_set, const bke::GeometryComponent::Type component_type, const eAttrDomain domain, + const int layer_index = -1, ExtraColumns extra_columns = {}) : object_eval_(object_eval), geometry_set_(std::move(geometry_set)), component_(geometry_set_.get_component(component_type)), domain_(domain), + layer_index_(layer_index), extra_columns_(std::move(extra_columns)) { } @@ -80,6 +84,9 @@ class GeometryDataSource : public DataSource { const SpreadsheetColumnID &column_id) const override; int tot_rows() const override; + + private: + std::optional get_component_attributes() const; }; class VolumeDataSource : public DataSource { diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc index 0ca2d8ac6f8..95925d93add 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc @@ -8,6 +8,8 @@ #include "DNA_windowmanager_types.h" #include "BKE_context.h" +#include "BKE_curves.hh" +#include "BKE_grease_pencil.hh" #include "BKE_volume.h" #include "RNA_access.hh" @@ -30,6 +32,7 @@ class GeometryDataSetTreeView; class GeometryDataSetTreeViewItem : public ui::AbstractTreeViewItem { bke::GeometryComponent::Type component_type_; + std::optional layer_index_; std::optional domain_; BIFIconID icon_; @@ -38,6 +41,15 @@ class GeometryDataSetTreeViewItem : public ui::AbstractTreeViewItem { StringRef label, BIFIconID icon); GeometryDataSetTreeViewItem(bke::GeometryComponent::Type component_type, + int layer_index, + StringRef label, + BIFIconID icon); + GeometryDataSetTreeViewItem(bke::GeometryComponent::Type component_type, + eAttrDomain domain, + StringRef label, + BIFIconID icon); + GeometryDataSetTreeViewItem(bke::GeometryComponent::Type component_type, + int layer_index, eAttrDomain domain, StringRef label, BIFIconID icon); @@ -70,6 +82,47 @@ class GeometryDataSetTreeView : public ui::AbstractTreeView { { } + void build_grease_pencil() + { + if (!U.experimental.use_grease_pencil_version3) { + return; + } + + GeometryDataSetTreeViewItem &grease_pencil = this->add_tree_item( + bke::GeometryComponent::Type::GreasePencil, + IFACE_("Grease Pencil"), + ICON_OUTLINER_DATA_GREASEPENCIL); + GeometryDataSetTreeViewItem &grease_pencil_layers = + grease_pencil.add_tree_item( + bke::GeometryComponent::Type::GreasePencil, + ATTR_DOMAIN_LAYER, + IFACE_("Layer"), + ICON_OUTLINER_DATA_GP_LAYER); + + if (!geometry_set_.has_grease_pencil()) { + return; + } + + const Span layers = + geometry_set_.get_grease_pencil()->layers(); + for (const int layer_i : layers.index_range()) { + const bke::greasepencil::Layer *layer = layers[layer_i]; + GeometryDataSetTreeViewItem &curve = + grease_pencil_layers.add_tree_item( + bke::GeometryComponent::Type::GreasePencil, layer_i, layer->name(), ICON_CURVE_DATA); + curve.add_tree_item(bke::GeometryComponent::Type::GreasePencil, + layer_i, + ATTR_DOMAIN_POINT, + IFACE_("Control Point"), + ICON_CURVE_BEZCIRCLE); + curve.add_tree_item(bke::GeometryComponent::Type::GreasePencil, + layer_i, + ATTR_DOMAIN_CURVE, + IFACE_("Spline"), + ICON_CURVE_PATH); + } + } + void build_tree() override { GeometryDataSetTreeViewItem &mesh = this->add_tree_item( @@ -94,18 +147,7 @@ class GeometryDataSetTreeView : public ui::AbstractTreeView { curve.add_tree_item( bke::GeometryComponent::Type::Curve, ATTR_DOMAIN_CURVE, IFACE_("Spline"), ICON_CURVE_PATH); - if (U.experimental.use_grease_pencil_version3) { - GeometryDataSetTreeViewItem &grease_pencil = - this->add_tree_item( - bke::GeometryComponent::Type::GreasePencil, - IFACE_("Grease Pencil"), - ICON_OUTLINER_DATA_GREASEPENCIL); - grease_pencil.add_tree_item( - bke::GeometryComponent::Type::GreasePencil, - ATTR_DOMAIN_LAYER, - IFACE_("Layer"), - ICON_OUTLINER_DATA_GP_LAYER); - } + this->build_grease_pencil(); GeometryDataSetTreeViewItem &pointcloud = this->add_tree_item( bke::GeometryComponent::Type::PointCloud, IFACE_("Point Cloud"), ICON_POINTCLOUD_DATA); @@ -131,6 +173,12 @@ GeometryDataSetTreeViewItem::GeometryDataSetTreeViewItem( label_ = label; this->set_collapsed(false); } +GeometryDataSetTreeViewItem::GeometryDataSetTreeViewItem( + bke::GeometryComponent::Type component_type, int layer_index, StringRef label, BIFIconID icon) + : component_type_(component_type), layer_index_(layer_index), icon_(icon) +{ + label_ = label; +} GeometryDataSetTreeViewItem::GeometryDataSetTreeViewItem( bke::GeometryComponent::Type component_type, eAttrDomain domain, @@ -140,6 +188,16 @@ GeometryDataSetTreeViewItem::GeometryDataSetTreeViewItem( { label_ = label; } +GeometryDataSetTreeViewItem::GeometryDataSetTreeViewItem( + bke::GeometryComponent::Type component_type, + int layer_index, + eAttrDomain domain, + StringRef label, + BIFIconID icon) + : component_type_(component_type), layer_index_(layer_index), domain_(domain), icon_(icon) +{ + label_ = label; +} void GeometryDataSetTreeViewItem::on_activate(bContext &C) { @@ -149,6 +207,9 @@ void GeometryDataSetTreeViewItem::on_activate(bContext &C) if (domain_) { tree_view.sspreadsheet_.attribute_domain = *domain_; } + if (layer_index_) { + tree_view.sspreadsheet_.active_layer_index = *layer_index_; + } PointerRNA ptr = RNA_pointer_create(&tree_view.screen_.id, &RNA_SpaceSpreadsheet, &sspreadsheet); RNA_property_update(&C, &ptr, RNA_struct_find_property(&ptr, "attribute_domain")); RNA_property_update(&C, &ptr, RNA_struct_find_property(&ptr, "geometry_component_type")); @@ -180,13 +241,19 @@ std::optional GeometryDataSetTreeViewItem::should_be_active() const return false; } + if (!layer_index_) { + return sspreadsheet.geometry_component_type == uint8_t(component_type_) && + sspreadsheet.attribute_domain == *domain_; + } + return sspreadsheet.geometry_component_type == uint8_t(component_type_) && - sspreadsheet.attribute_domain == *domain_; + sspreadsheet.attribute_domain == *domain_ && + sspreadsheet.active_layer_index == *layer_index_; } bool GeometryDataSetTreeViewItem::supports_collapsing() const { - return false; + return true; } GeometryDataSetTreeView &GeometryDataSetTreeViewItem::get_tree() const @@ -211,6 +278,15 @@ std::optional GeometryDataSetTreeViewItem::count() const return std::nullopt; } + if (component_type_ == bke::GeometryComponent::Type::GreasePencil && layer_index_) { + if (const bke::greasepencil::Drawing *drawing = + bke::greasepencil::get_eval_grease_pencil_layer_drawing(*geometry.get_grease_pencil(), + *layer_index_)) + { + return drawing->strokes().attributes().domain_size(*domain_); + } + } + if (const bke::GeometryComponent *component = geometry.get_component(component_type_)) { return component->attribute_domain_size(*domain_); } diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 5c8c055ca50..9eced9bae75 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -1985,9 +1985,12 @@ typedef struct SpaceSpreadsheet { uint8_t attribute_domain; /* eSpaceSpreadsheet_ObjectEvalState. */ uint8_t object_eval_state; + /* Active grease pencil layer index for grease pencil component. */ + int active_layer_index; /* eSpaceSpreadsheet_Flag. */ uint32_t flag; + char _pad1[4]; SpaceSpreadsheet_Runtime *runtime; } SpaceSpreadsheet; diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index c859c83bda4..2432e03e25d 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -41,6 +41,7 @@ using bke::GeometryComponentEditData; using bke::GeometrySet; using bke::GreasePencilComponent; using bke::GSpanAttributeWriter; +using bke::GreasePencilComponent; using bke::InstancesComponent; using bke::MeshComponent; using bke::MutableAttributeAccessor;