Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Schempp <fabianschempp@googlemail.com>2021-06-25 08:57:24 +0300
committerFabian Schempp <fabianschempp@googlemail.com>2021-06-25 08:57:24 +0300
commitae085e301c2aac0d6956609bfe93a90a19f0e235 (patch)
tree38b86749807915a6b6d46504a2acb90e41a4a77a /source/blender/editors/space_spreadsheet
parent841df831e89dfc4011c323203c2efb8265dc1878 (diff)
Spreadsheet: Dataset region for spreadsheet editor
This patch adds a left aligned sidebar to the spreadsheet editor. This Sidebar can be used to navigate the geometry component types and attribute domains. It also provides a quick overview of domain sizes. It replaces the two dropdowns in the regions header. Next step will be to add the domain cycling shortcut using the CTRL + mouse wheel. Reviewer: Dalai Felinto (dfelinto), Julian Eisel (Severin), Hans Goudey (HooglyBoogly). Differential Revision: https://developer.blender.org/D11046
Diffstat (limited to 'source/blender/editors/space_spreadsheet')
-rw-r--r--source/blender/editors/space_spreadsheet/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_spreadsheet/space_spreadsheet.cc109
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_context.cc4
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc9
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc277
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh64
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc112
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.hh68
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_intern.hh13
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_ops.cc53
10 files changed, 695 insertions, 18 deletions
diff --git a/source/blender/editors/space_spreadsheet/CMakeLists.txt b/source/blender/editors/space_spreadsheet/CMakeLists.txt
index 7e3f3db9bc8..1ea6593588a 100644
--- a/source/blender/editors/space_spreadsheet/CMakeLists.txt
+++ b/source/blender/editors/space_spreadsheet/CMakeLists.txt
@@ -38,6 +38,8 @@ set(SRC
spreadsheet_column.cc
spreadsheet_data_source.cc
spreadsheet_data_source_geometry.cc
+ spreadsheet_dataset_draw.cc
+ spreadsheet_dataset_layout.cc
spreadsheet_draw.cc
spreadsheet_layout.cc
spreadsheet_ops.cc
@@ -50,6 +52,8 @@ set(SRC
spreadsheet_column_values.hh
spreadsheet_data_source.hh
spreadsheet_data_source_geometry.hh
+ spreadsheet_dataset_draw.hh
+ spreadsheet_dataset_layout.hh
spreadsheet_draw.hh
spreadsheet_intern.hh
spreadsheet_layout.hh
diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
index 8c42f28b5f4..f8654500044 100644
--- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
+++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
@@ -47,6 +47,7 @@
#include "spreadsheet_context.hh"
#include "spreadsheet_data_source_geometry.hh"
+#include "spreadsheet_dataset_draw.hh"
#include "spreadsheet_intern.hh"
#include "spreadsheet_layout.hh"
#include "spreadsheet_row_filter.hh"
@@ -80,6 +81,15 @@ static SpaceLink *spreadsheet_create(const ScrArea *UNUSED(area), const Scene *U
}
{
+ /* Dataset Region */
+ ARegion *region = (ARegion *)MEM_callocN(sizeof(ARegion), "spreadsheet dataset region");
+ BLI_addtail(&spreadsheet_space->regionbase, region);
+ region->regiontype = RGN_TYPE_CHANNELS;
+ region->alignment = RGN_ALIGN_LEFT;
+ region->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
+ }
+
+ {
/* Properties region. */
ARegion *region = (ARegion *)MEM_callocN(sizeof(ARegion), "spreadsheet right region");
BLI_addtail(&spreadsheet_space->regionbase, region);
@@ -195,7 +205,7 @@ static void spreadsheet_main_region_init(wmWindowManager *wm, ARegion *region)
}
}
-ID *ED_spreadsheet_get_current_id(struct SpaceSpreadsheet *sspreadsheet)
+ID *ED_spreadsheet_get_current_id(const struct SpaceSpreadsheet *sspreadsheet)
{
if (BLI_listbase_is_empty(&sspreadsheet->context_path)) {
return nullptr;
@@ -263,7 +273,7 @@ static void update_context_path_from_context(const bContext *C)
}
}
-static void update_context_path(const bContext *C)
+void spreadsheet_update_context_path(const bContext *C)
{
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
if (sspreadsheet->flag & SPREADSHEET_FLAG_PINNED) {
@@ -274,28 +284,40 @@ static void update_context_path(const bContext *C)
}
}
-static std::unique_ptr<DataSource> get_data_source(const bContext *C)
+Object *spreadsheet_get_object_eval(const SpaceSpreadsheet *sspreadsheet,
+ const Depsgraph *depsgraph)
{
- Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
ID *used_id = ED_spreadsheet_get_current_id(sspreadsheet);
if (used_id == nullptr) {
- return {};
+ return nullptr;
}
const ID_Type id_type = GS(used_id->name);
if (id_type != ID_OB) {
- return {};
+ return nullptr;
}
Object *object_orig = (Object *)used_id;
if (!ELEM(object_orig->type, OB_MESH, OB_POINTCLOUD, OB_VOLUME)) {
- return {};
+ return nullptr;
}
+
Object *object_eval = DEG_get_evaluated_object(depsgraph, object_orig);
if (object_eval == nullptr) {
- return {};
+ return nullptr;
}
- return data_source_from_geometry(C, object_eval);
+ return object_eval;
+}
+
+static std::unique_ptr<DataSource> get_data_source(const bContext *C)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
+
+ Object *object_eval = spreadsheet_get_object_eval(sspreadsheet, depsgraph);
+ if (object_eval) {
+ return data_source_from_geometry(C, object_eval);
+ }
+ return {};
}
static float get_column_width(const ColumnValues &values)
@@ -358,7 +380,7 @@ static void update_visible_columns(ListBase &columns, DataSource &data_source)
static void spreadsheet_main_region_draw(const bContext *C, ARegion *region)
{
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
- update_context_path(C);
+ spreadsheet_update_context_path(C);
std::unique_ptr<DataSource> data_source = get_data_source(C);
if (!data_source) {
@@ -442,7 +464,7 @@ static void spreadsheet_header_region_init(wmWindowManager *UNUSED(wm), ARegion
static void spreadsheet_header_region_draw(const bContext *C, ARegion *region)
{
- update_context_path(C);
+ spreadsheet_update_context_path(C);
ED_region_header(C, region);
}
@@ -534,6 +556,59 @@ static void spreadsheet_footer_region_listener(const wmRegionListenerParams *UNU
{
}
+static void spreadsheet_dataset_region_listener(const wmRegionListenerParams *params)
+{
+ ARegion *region = params->region;
+ wmNotifier *wmn = params->notifier;
+
+ switch (wmn->category) {
+ case NC_SCENE: {
+ switch (wmn->data) {
+ case ND_FRAME:
+ ED_region_tag_redraw(region);
+ break;
+ }
+ break;
+ }
+ case NC_TEXTURE:
+ ED_region_tag_redraw(region);
+ break;
+ }
+
+ spreadsheet_header_region_listener(params);
+}
+
+static void spreadsheet_dataset_region_init(wmWindowManager *wm, ARegion *region)
+{
+ region->v2d.scroll |= V2D_SCROLL_RIGHT;
+ region->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP | V2D_SCROLL_BOTTOM);
+ region->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
+ region->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE;
+
+ UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
+
+ wmKeyMap *keymap = WM_keymap_ensure(
+ wm->defaultconf, "Spreadsheet Generic", SPACE_SPREADSHEET, 0);
+ WM_event_add_keymap_handler(&region->handlers, keymap);
+}
+
+static void spreadsheet_dataset_region_draw(const bContext *C, ARegion *region)
+{
+ spreadsheet_update_context_path(C);
+
+ View2D *v2d = &region->v2d;
+ UI_view2d_view_ortho(v2d);
+ UI_ThemeClearColor(TH_BACK);
+
+ draw_dataset_in_region(C, region);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ UI_view2d_scrollers_draw(v2d, NULL);
+}
+
static void spreadsheet_sidebar_init(wmWindowManager *wm, ARegion *region)
{
UI_panel_category_active_set_default(region, "Filters");
@@ -619,5 +694,15 @@ void ED_spacetype_spreadsheet(void)
register_row_filter_panels(*art);
+ /* regions: channels */
+ art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spreadsheet dataset region");
+ art->regionid = RGN_TYPE_CHANNELS;
+ art->prefsizex = 200 + V2D_SCROLL_WIDTH;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
+ art->init = spreadsheet_dataset_region_init;
+ art->draw = spreadsheet_dataset_region_draw;
+ art->listener = spreadsheet_dataset_region_listener;
+ BLI_addhead(&st->regiontypes, art);
+
BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_context.cc b/source/blender/editors/space_spreadsheet/spreadsheet_context.cc
index 3eb43338908..af6ab5d1b92 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_context.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_context.cc
@@ -255,11 +255,11 @@ void ED_spreadsheet_context_path_update_tag(SpaceSpreadsheet *sspreadsheet)
blender::ed::spreadsheet::spreadsheet_context_update_tag(sspreadsheet);
}
-uint64_t ED_spreadsheet_context_path_hash(SpaceSpreadsheet *sspreadsheet)
+uint64_t ED_spreadsheet_context_path_hash(const SpaceSpreadsheet *sspreadsheet)
{
BLI_HashMurmur2A mm2;
BLI_hash_mm2a_init(&mm2, 1234);
- LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) {
+ LISTBASE_FOREACH (const SpreadsheetContext *, context, &sspreadsheet->context_path) {
blender::ed::spreadsheet::spreadsheet_context_hash(context, &mm2);
}
return BLI_hash_mm2a_end(&mm2);
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 0c76c8b7a15..6d244a1bda6 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
@@ -385,9 +385,9 @@ int InstancesDataSource::tot_rows() const
return component_->instances_amount();
}
-static GeometrySet get_display_geometry_set(SpaceSpreadsheet *sspreadsheet,
- Object *object_eval,
- const GeometryComponentType used_component_type)
+GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspreadsheet,
+ Object *object_eval,
+ const GeometryComponentType used_component_type)
{
GeometrySet geometry_set;
if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL) {
@@ -470,7 +470,8 @@ std::unique_ptr<DataSource> data_source_from_geometry(const bContext *C, Object
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
const AttributeDomain domain = (AttributeDomain)sspreadsheet->attribute_domain;
const GeometryComponentType component_type = get_display_component_type(C, object_eval);
- GeometrySet geometry_set = get_display_geometry_set(sspreadsheet, object_eval, component_type);
+ GeometrySet geometry_set = spreadsheet_get_display_geometry_set(
+ sspreadsheet, object_eval, component_type);
if (!geometry_set.has(component_type)) {
return {};
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc
new file mode 100644
index 00000000000..1fa6e47fcdf
--- /dev/null
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc
@@ -0,0 +1,277 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <array>
+
+#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_context.h"
+
+#include "BLF_api.h"
+
+#include "BLI_rect.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "WM_types.h"
+
+#include "spreadsheet_dataset_draw.hh"
+#include "spreadsheet_draw.hh"
+#include "spreadsheet_intern.hh"
+
+static int is_component_row_selected(struct uiBut *but, const void *arg)
+{
+ SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)arg;
+
+ GeometryComponentType component = (GeometryComponentType)UI_but_datasetrow_component_get(but);
+ AttributeDomain domain = (AttributeDomain)UI_but_datasetrow_domain_get(but);
+
+ const bool is_component_selected = (GeometryComponentType)
+ sspreadsheet->geometry_component_type == component;
+ const bool is_domain_selected = (AttributeDomain)sspreadsheet->attribute_domain == domain;
+ bool is_selected = is_component_selected && is_domain_selected;
+
+ if (component == GEO_COMPONENT_TYPE_INSTANCES) {
+ is_selected = is_component_selected;
+ }
+
+ return is_selected;
+}
+
+namespace blender::ed::spreadsheet {
+
+/* -------------------------------------------------------------------- */
+/* Draw Context */
+
+class DatasetDrawContext {
+ std::array<int, 2> mval_;
+
+ public:
+ const SpaceSpreadsheet *sspreadsheet;
+ Object *object_eval;
+ /* Current geometry set, changes per component. */
+ GeometrySet current_geometry_set;
+
+ DatasetDrawContext(const bContext *C);
+
+ GeometrySet geometry_set_from_component(GeometryComponentType component);
+ const std::array<int, 2> &cursor_mval() const;
+};
+
+DatasetDrawContext::DatasetDrawContext(const bContext *C)
+ : sspreadsheet(CTX_wm_space_spreadsheet(C)),
+ object_eval(spreadsheet_get_object_eval(sspreadsheet, CTX_data_depsgraph_pointer(C)))
+{
+ const wmWindow *win = CTX_wm_window(C);
+ const ARegion *region = CTX_wm_region(C);
+ mval_ = {win->eventstate->x - region->winrct.xmin, win->eventstate->y - region->winrct.ymin};
+}
+
+GeometrySet DatasetDrawContext::geometry_set_from_component(GeometryComponentType component)
+{
+ return spreadsheet_get_display_geometry_set(sspreadsheet, object_eval, component);
+}
+
+const std::array<int, 2> &DatasetDrawContext::cursor_mval() const
+{
+ return mval_;
+}
+
+/* -------------------------------------------------------------------- */
+/* Drawer */
+
+DatasetRegionDrawer::DatasetRegionDrawer(const ARegion *region,
+ uiBlock &block,
+ DatasetDrawContext &draw_context)
+ : row_height(UI_UNIT_Y),
+ xmin(region->v2d.cur.xmin),
+ xmax(region->v2d.cur.xmax),
+ block(block),
+ v2d(region->v2d),
+ draw_context(draw_context)
+{
+}
+
+void DatasetRegionDrawer::draw_hierarchy(const DatasetLayoutHierarchy &layout)
+{
+ for (const DatasetComponentLayoutInfo &component : layout.components) {
+ draw_context.current_geometry_set = draw_context.geometry_set_from_component(component.type);
+
+ draw_component_row(component);
+
+ /* Iterate attribute domains, skip unset ones (storage has to be in a enum-based, fixed size
+ * array so uses optionals to support skipping enum values that shouldn't be displayed for a
+ * component). */
+ for (auto &optional_domain : component.attr_domains) {
+ if (!optional_domain) {
+ continue;
+ }
+
+ const DatasetAttrDomainLayoutInfo &domain_info = *optional_domain;
+ draw_attribute_domain_row(component, domain_info);
+ }
+ }
+}
+
+static int element_count_from_component_domain(const GeometrySet &geometry_set,
+ GeometryComponentType component,
+ AttributeDomain domain)
+{
+ if (geometry_set.has_mesh() && component == GEO_COMPONENT_TYPE_MESH) {
+ const MeshComponent *mesh_component = geometry_set.get_component_for_read<MeshComponent>();
+ return mesh_component->attribute_domain_size(domain);
+ }
+
+ if (geometry_set.has_pointcloud() && component == GEO_COMPONENT_TYPE_POINT_CLOUD) {
+ const PointCloudComponent *point_cloud_component =
+ geometry_set.get_component_for_read<PointCloudComponent>();
+ return point_cloud_component->attribute_domain_size(domain);
+ }
+
+ if (geometry_set.has_instances() && component == GEO_COMPONENT_TYPE_INSTANCES) {
+ const InstancesComponent *instances_component =
+ geometry_set.get_component_for_read<InstancesComponent>();
+ return instances_component->instances_amount();
+ }
+
+ if (geometry_set.has_volume() && component == GEO_COMPONENT_TYPE_VOLUME) {
+ const VolumeComponent *volume_component =
+ geometry_set.get_component_for_read<VolumeComponent>();
+ return volume_component->attribute_domain_size(domain);
+ }
+
+ if (geometry_set.has_curve() && component == GEO_COMPONENT_TYPE_CURVE) {
+ const CurveComponent *curve_component = geometry_set.get_component_for_read<CurveComponent>();
+ return curve_component->attribute_domain_size(domain);
+ }
+
+ return 0;
+}
+
+void DatasetRegionDrawer::draw_dataset_row(const int indentation,
+ const GeometryComponentType component,
+ const std::optional<AttributeDomain> domain,
+ BIFIconID icon,
+ const char *label,
+ const bool is_active)
+{
+
+ const float row_height = UI_UNIT_Y;
+ const float padding_x = UI_UNIT_X * 0.25f;
+
+ const rctf rect = {float(xmin) + padding_x,
+ float(xmax) - V2D_SCROLL_HANDLE_WIDTH,
+ ymin_offset - row_height,
+ ymin_offset};
+
+ char element_count[7];
+ BLI_str_format_attribute_domain_size(
+ element_count,
+ domain ? element_count_from_component_domain(
+ draw_context.current_geometry_set, component, *domain) :
+ 0);
+
+ std::string label_and_element_count = label;
+ label_and_element_count += UI_SEP_CHAR;
+ label_and_element_count += element_count;
+
+ uiBut *bt = uiDefIconTextButO(&block,
+ UI_BTYPE_DATASETROW,
+ "SPREADSHEET_OT_change_spreadsheet_data_source",
+ 0,
+ icon,
+ label,
+ rect.xmin,
+ rect.ymin,
+ BLI_rctf_size_x(&rect),
+ BLI_rctf_size_y(&rect),
+ NULL);
+
+ UI_but_datasetrow_indentation_set(bt, indentation);
+
+ if (is_active) {
+ UI_but_hint_drawstr_set(bt, element_count);
+ UI_but_datasetrow_component_set(bt, component);
+ if (domain) {
+ UI_but_datasetrow_domain_set(bt, *domain);
+ }
+ UI_but_func_pushed_state_set(bt, &is_component_row_selected, draw_context.sspreadsheet);
+
+ PointerRNA *but_ptr = UI_but_operator_ptr_get((uiBut *)bt);
+ RNA_int_set(but_ptr, "component_type", component);
+ if (domain) {
+ RNA_int_set(but_ptr, "attribute_domain_type", *domain);
+ }
+ }
+
+ ymin_offset -= row_height;
+}
+
+void DatasetRegionDrawer::draw_component_row(const DatasetComponentLayoutInfo &component_info)
+{
+ if (component_info.type == GEO_COMPONENT_TYPE_INSTANCES) {
+ draw_dataset_row(
+ 0, component_info.type, std::nullopt, component_info.icon, component_info.label, true);
+ }
+ else {
+ draw_dataset_row(
+ 0, component_info.type, std::nullopt, component_info.icon, component_info.label, false);
+ }
+}
+
+void DatasetRegionDrawer::draw_attribute_domain_row(
+ const DatasetComponentLayoutInfo &component_info,
+ const DatasetAttrDomainLayoutInfo &domain_info)
+{
+ draw_dataset_row(
+ 1, component_info.type, domain_info.type, domain_info.icon, domain_info.label, true);
+}
+
+/* -------------------------------------------------------------------- */
+/* Drawer */
+
+void draw_dataset_in_region(const bContext *C, ARegion *region)
+{
+ DatasetDrawContext draw_context{C};
+ if (!draw_context.object_eval) {
+ /* No object means nothing to display. Keep the region empty. */
+ return;
+ }
+
+ uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
+
+ DatasetRegionDrawer drawer{region, *block, draw_context};
+
+ /* Start with an offset to align buttons to spreadsheet rows. Use spreadsheet drawing info for
+ * that. */
+ drawer.ymin_offset = -SpreadsheetDrawer().top_row_height + drawer.row_height;
+
+ const DatasetLayoutHierarchy hierarchy = dataset_layout_hierarchy();
+ drawer.draw_hierarchy(hierarchy);
+#ifndef NDEBUG
+ dataset_layout_hierarchy_sanity_check(hierarchy);
+#endif
+
+ UI_block_end(C, block);
+ UI_view2d_totRect_set(&region->v2d, region->winx, abs(drawer.ymin_offset));
+ UI_block_draw(C, block);
+}
+
+} // namespace blender::ed::spreadsheet
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh
new file mode 100644
index 00000000000..d9e6d882c2a
--- /dev/null
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.hh
@@ -0,0 +1,64 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#include <array>
+
+#include "BKE_geometry_set.hh"
+#include "UI_interface.h"
+#include "spreadsheet_dataset_layout.hh"
+
+struct ARegion;
+struct uiBlock;
+struct View2D;
+struct bContext;
+
+namespace blender::ed::spreadsheet {
+
+class DatasetDrawContext;
+
+class DatasetRegionDrawer {
+ public:
+ const int row_height;
+ float ymin_offset = 0;
+
+ int xmin;
+ int xmax;
+ uiBlock &block;
+ const View2D &v2d;
+ DatasetDrawContext &draw_context;
+
+ DatasetRegionDrawer(const ARegion *region, uiBlock &block, DatasetDrawContext &draw_context);
+
+ void draw_hierarchy(const DatasetLayoutHierarchy &layout);
+
+ void draw_attribute_domain_row(const DatasetComponentLayoutInfo &component,
+ const DatasetAttrDomainLayoutInfo &domain_info);
+ void draw_component_row(const DatasetComponentLayoutInfo &component_info);
+
+ private:
+ void draw_dataset_row(const int indentation,
+ const GeometryComponentType component,
+ const std::optional<AttributeDomain> domain,
+ const BIFIconID icon,
+ const char *label,
+ const bool is_active);
+};
+
+void draw_dataset_in_region(const bContext *C, ARegion *region);
+
+} // namespace blender::ed::spreadsheet
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc
new file mode 100644
index 00000000000..e9f2c51a6da
--- /dev/null
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.cc
@@ -0,0 +1,112 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <optional>
+
+#include "BLI_span.hh"
+
+#include "BLT_translation.h"
+
+#include "spreadsheet_dataset_layout.hh"
+
+namespace blender::ed::spreadsheet {
+
+#define ATTR_INFO(type, label, icon) \
+ std::optional<DatasetAttrDomainLayoutInfo> \
+ { \
+ std::in_place, type, label, icon \
+ }
+#define ATTR_INFO_NONE(type) \
+ { \
+ std::nullopt \
+ }
+
+/**
+ * Definion for the component->attribute-domain hierarchy.
+ * Constructed at compile time.
+ *
+ * \warning: Order of attribute-domains matters! It __must__ match the #AttributeDomain definition
+ * and fill gaps with unset optionals (i.e. `std::nullopt`). Would be nice to use array
+ * designators for this (which C++ doesn't support).
+ */
+constexpr DatasetComponentLayoutInfo DATASET_layout_hierarchy[] = {
+ {
+ GEO_COMPONENT_TYPE_MESH,
+ N_("Mesh"),
+ ICON_MESH_DATA,
+ {
+ ATTR_INFO(ATTR_DOMAIN_POINT, N_("Vertex"), ICON_VERTEXSEL),
+ ATTR_INFO(ATTR_DOMAIN_EDGE, N_("Edge"), ICON_EDGESEL),
+ ATTR_INFO(ATTR_DOMAIN_FACE, N_("Face"), ICON_FACESEL),
+ ATTR_INFO(ATTR_DOMAIN_CORNER, N_("Face Corner"), ICON_NODE_CORNER),
+ },
+ },
+ {
+ GEO_COMPONENT_TYPE_CURVE,
+ N_("Curves"),
+ ICON_CURVE_DATA,
+ {
+ ATTR_INFO(ATTR_DOMAIN_POINT, N_("Control Point"), ICON_CURVE_BEZCIRCLE),
+ ATTR_INFO_NONE(ATTR_DOMAIN_EDGE),
+ ATTR_INFO_NONE(ATTR_DOMAIN_CORNER),
+ ATTR_INFO_NONE(ATTR_DOMAIN_FACE),
+ ATTR_INFO(ATTR_DOMAIN_CURVE, N_("Spline"), ICON_CURVE_PATH),
+ },
+ },
+ {
+ GEO_COMPONENT_TYPE_POINT_CLOUD,
+ N_("Point Cloud"),
+ ICON_POINTCLOUD_DATA,
+ {
+ ATTR_INFO(ATTR_DOMAIN_POINT, N_("Point"), ICON_PARTICLE_POINT),
+ },
+ },
+ {
+ GEO_COMPONENT_TYPE_INSTANCES,
+ N_("Instances"),
+ ICON_EMPTY_AXIS,
+ {},
+ },
+};
+
+#undef ATTR_INFO
+#undef ATTR_INFO_LABEL
+
+DatasetLayoutHierarchy dataset_layout_hierarchy()
+{
+ return DatasetLayoutHierarchy{
+ Span{DATASET_layout_hierarchy, ARRAY_SIZE(DATASET_layout_hierarchy)}};
+}
+
+#ifndef NDEBUG
+/**
+ * Debug-only sanity check for correct attribute domain initialization (order/indices must
+ * match AttributeDomain). This doesn't check for all possible missuses, but should catch the most
+ * likely mistakes.
+ */
+void dataset_layout_hierarchy_sanity_check(const DatasetLayoutHierarchy &hierarchy)
+{
+ for (const DatasetComponentLayoutInfo &component : hierarchy.components) {
+ for (uint i = 0; i < component.attr_domains.size(); i++) {
+ if (component.attr_domains[i]) {
+ BLI_assert(component.attr_domains[i]->type == static_cast<AttributeDomain>(i));
+ }
+ }
+ }
+}
+#endif
+
+} // namespace blender::ed::spreadsheet
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.hh b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.hh
new file mode 100644
index 00000000000..d463739a0fa
--- /dev/null
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_layout.hh
@@ -0,0 +1,68 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#include <array>
+#include <optional>
+
+/* Enum definitions... */
+#include "BKE_attribute.h"
+#include "BKE_geometry_set.h"
+
+#include "BLI_span.hh"
+
+/* More enum definitions... */
+#include "UI_resources.h"
+
+#pragma once
+
+namespace blender::ed::spreadsheet {
+
+struct DatasetAttrDomainLayoutInfo {
+ AttributeDomain type;
+ const char *label;
+ BIFIconID icon;
+
+ constexpr DatasetAttrDomainLayoutInfo(AttributeDomain type, const char *label, BIFIconID icon)
+ : type(type), label(label), icon(icon)
+ {
+ }
+};
+
+struct DatasetComponentLayoutInfo {
+ GeometryComponentType type;
+ const char *label;
+ BIFIconID icon;
+ /** Array of attribute-domains. Has to be fixed size based on #AttributeDomain enum, but not all
+ * values need displaying for all parent components. Hence the optional use. */
+ using AttrDomainArray = std::array<std::optional<DatasetAttrDomainLayoutInfo>, ATTR_DOMAIN_NUM>;
+ const AttrDomainArray attr_domains;
+};
+
+struct DatasetLayoutHierarchy {
+ /** The components for display (with layout info like icon and label). Each component stores
+ * the attribute domains it wants to display (also with layout info like icon and label). */
+ const Span<DatasetComponentLayoutInfo> components;
+};
+
+DatasetLayoutHierarchy dataset_layout_hierarchy();
+
+#ifndef NDEBUG
+void dataset_layout_hierarchy_sanity_check(const DatasetLayoutHierarchy &hierarchy);
+#endif
+
+} // namespace blender::ed::spreadsheet
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_intern.hh b/source/blender/editors/space_spreadsheet/spreadsheet_intern.hh
index 7e3b79a6706..8be5283fd63 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_intern.hh
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_intern.hh
@@ -16,10 +16,23 @@
#pragma once
+#include "BKE_geometry_set.hh"
+
typedef struct SpaceSpreadsheet_Runtime {
int visible_rows;
int tot_rows;
int tot_columns;
} SpaceSpreadsheet_Runtime;
+struct bContext;
+
void spreadsheet_operatortypes(void);
+void spreadsheet_update_context_path(const bContext *C);
+Object *spreadsheet_get_object_eval(const SpaceSpreadsheet *sspreadsheet,
+ const Depsgraph *depsgraph);
+
+namespace blender::ed::spreadsheet {
+GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspreadsheet,
+ Object *object_eval,
+ const GeometryComponentType used_component_type);
+}
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_ops.cc b/source/blender/editors/space_spreadsheet/spreadsheet_ops.cc
index fcbc37346e6..ceb4cd84cde 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_ops.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_ops.cc
@@ -13,6 +13,17 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "BKE_screen.h"
+
+#include "DNA_space_types.h"
+
+#include "ED_screen.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
#include "BLI_listbase.h"
@@ -89,8 +100,50 @@ static void SPREADSHEET_OT_remove_row_filter_rule(wmOperatorType *ot)
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
}
+static int select_component_domain_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
+{
+ GeometryComponentType component_type = static_cast<GeometryComponentType>(
+ RNA_int_get(op->ptr, "component_type"));
+ AttributeDomain attribute_domain = static_cast<AttributeDomain>(
+ RNA_int_get(op->ptr, "attribute_domain_type"));
+
+ SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
+ sspreadsheet->geometry_component_type = component_type;
+ sspreadsheet->attribute_domain = attribute_domain;
+
+ /* Refresh header and main region. */
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static void SPREADSHEET_OT_change_spreadsheet_data_source(wmOperatorType *ot)
+{
+ ot->name = "Change Visible Data Source";
+ ot->description = "Change visible data source in the spreadsheet";
+ ot->idname = "SPREADSHEET_OT_change_spreadsheet_data_source";
+
+ ot->invoke = select_component_domain_invoke;
+
+ RNA_def_int(ot->srna, "component_type", 0, 0, INT16_MAX, "Component Type", "", 0, INT16_MAX);
+ RNA_def_int(ot->srna,
+ "attribute_domain_type",
+ 0,
+ 0,
+ INT16_MAX,
+ "Attribute Domain Type",
+ "",
+ 0,
+ INT16_MAX);
+
+ ot->flag = OPTYPE_INTERNAL;
+}
+
void spreadsheet_operatortypes()
{
WM_operatortype_append(SPREADSHEET_OT_add_row_filter_rule);
WM_operatortype_append(SPREADSHEET_OT_remove_row_filter_rule);
+ WM_operatortype_append(SPREADSHEET_OT_change_spreadsheet_data_source);
}