GPv3: Implement expanding of Grease Pencil component in the spreadsheet

This patch adds the ability for users to expand the grease pencil component in the spreadsheet and see the values for each `CurvesGeometry` in each layer.

It also makes it so that all the geometry components can be expanded for consistency.

Pull Request: https://projects.blender.org/blender/blender/pulls/113507
This commit is contained in:
Falk David
2023-10-12 16:51:44 +02:00
committed by Falk David
parent 3792c2720d
commit faa24698a5
6 changed files with 168 additions and 27 deletions

View File

@@ -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);

View File

@@ -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<ColumnValues> build_mesh_debug_columns(const Mesh &mesh,
void GeometryDataSource::foreach_default_column_ids(
FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const
{
if (!component_->attributes().has_value()) {
std::optional<const bke::AttributeAccessor> 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<ColumnValues> GeometryDataSource::get_column_values(
const SpreadsheetColumnID &column_id) const
{
if (!component_->attributes().has_value()) {
std::optional<const bke::AttributeAccessor> 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<ColumnValues> GeometryDataSource::get_column_values(
}
}
}
else if (component_->type() == bke::GeometryComponent::Type::GreasePencil) {
if (const GreasePencil *grease_pencil =
static_cast<const bke::GreasePencilComponent &>(*component_).get())
{
if (domain_ == ATTR_DOMAIN_LAYER && STREQ(column_id.name, "Name")) {
const Span<const bke::greasepencil::Layer *> layers = grease_pencil->layers();
return std::make_unique<ColumnValues>(
column_id.name, VArray<std::string>::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<const bke::MeshComponent &>(*component_);
if (const Mesh *mesh = component.get()) {
@@ -277,7 +295,7 @@ std::unique_ptr<ColumnValues> 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<ColumnValues> GeometryDataSource::get_column_values(
int GeometryDataSource::tot_rows() const
{
if (!component_->attributes().has_value()) {
std::optional<const bke::AttributeAccessor> 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<const bke::AttributeAccessor> 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<void(const SpreadsheetColumnID &, bool is_extra)> fn) const
{
@@ -524,6 +564,11 @@ bke::GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *ss
geometry_set.replace_curves(&const_cast<Curves &>(curves_id),
bke::GeometryOwnershipType::ReadOnly);
}
else if (object_orig->type == OB_GREASE_PENCIL) {
const GreasePencil &grease_pencil = *static_cast<const GreasePencil *>(object_orig->data);
geometry_set.replace_grease_pencil(&const_cast<GreasePencil &>(grease_pencil),
bke::GeometryOwnershipType::ReadOnly);
}
}
else {
if (BLI_listbase_is_single(&sspreadsheet->viewer_path.path)) {
@@ -555,6 +600,7 @@ std::unique_ptr<DataSource> 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<DataSource> data_source_from_geometry(const bContext *C, Object
return std::make_unique<VolumeDataSource>(std::move(geometry_set));
}
return std::make_unique<GeometryDataSource>(
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

View File

@@ -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<const bke::AttributeAccessor> get_component_attributes() const;
};
class VolumeDataSource : public DataSource {

View File

@@ -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<int> layer_index_;
std::optional<eAttrDomain> 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<GeometryDataSetTreeViewItem>(
bke::GeometryComponent::Type::GreasePencil,
IFACE_("Grease Pencil"),
ICON_OUTLINER_DATA_GREASEPENCIL);
GeometryDataSetTreeViewItem &grease_pencil_layers =
grease_pencil.add_tree_item<GeometryDataSetTreeViewItem>(
bke::GeometryComponent::Type::GreasePencil,
ATTR_DOMAIN_LAYER,
IFACE_("Layer"),
ICON_OUTLINER_DATA_GP_LAYER);
if (!geometry_set_.has_grease_pencil()) {
return;
}
const Span<const bke::greasepencil::Layer *> 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<GeometryDataSetTreeViewItem>(
bke::GeometryComponent::Type::GreasePencil, layer_i, layer->name(), ICON_CURVE_DATA);
curve.add_tree_item<GeometryDataSetTreeViewItem>(bke::GeometryComponent::Type::GreasePencil,
layer_i,
ATTR_DOMAIN_POINT,
IFACE_("Control Point"),
ICON_CURVE_BEZCIRCLE);
curve.add_tree_item<GeometryDataSetTreeViewItem>(bke::GeometryComponent::Type::GreasePencil,
layer_i,
ATTR_DOMAIN_CURVE,
IFACE_("Spline"),
ICON_CURVE_PATH);
}
}
void build_tree() override
{
GeometryDataSetTreeViewItem &mesh = this->add_tree_item<GeometryDataSetTreeViewItem>(
@@ -94,18 +147,7 @@ class GeometryDataSetTreeView : public ui::AbstractTreeView {
curve.add_tree_item<GeometryDataSetTreeViewItem>(
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<GeometryDataSetTreeViewItem>(
bke::GeometryComponent::Type::GreasePencil,
IFACE_("Grease Pencil"),
ICON_OUTLINER_DATA_GREASEPENCIL);
grease_pencil.add_tree_item<GeometryDataSetTreeViewItem>(
bke::GeometryComponent::Type::GreasePencil,
ATTR_DOMAIN_LAYER,
IFACE_("Layer"),
ICON_OUTLINER_DATA_GP_LAYER);
}
this->build_grease_pencil();
GeometryDataSetTreeViewItem &pointcloud = this->add_tree_item<GeometryDataSetTreeViewItem>(
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<bool> 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<int> 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_);
}

View File

@@ -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;

View File

@@ -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;