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:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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_);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user