Compare commits
40 Commits
windows_ma
...
temp-sprea
Author | SHA1 | Date | |
---|---|---|---|
1fbdf19ee2 | |||
5355e9e603 | |||
f1ebcfeef9 | |||
6fe76f602f | |||
f5dee9b7a5 | |||
f5f58882ef | |||
72198d508a | |||
3f4f28082f | |||
92ce1c8367 | |||
7680d4fc6a | |||
8d7866f4b3 | |||
c9c88b9626 | |||
deff5f1cd0 | |||
bdcdc973a7 | |||
ec96577057 | |||
a79288785c | |||
7612308189 | |||
f80bd477ac | |||
582928f081 | |||
1d8983c549 | |||
6c1ef12e80 | |||
94cc56b450 | |||
5877465c20 | |||
9094e3cd77 | |||
c62d1b5476 | |||
8919c68adb | |||
5e5242dbc9 | |||
1b31d7bf47 | |||
9f2b978617 | |||
b770c9ed40 | |||
d0fd407985 | |||
f3b85c2e6c | |||
7fe14a43b9 | |||
5da0baff4e | |||
95740e1153 | |||
92aa3e75a6 | |||
4a6c00a9eb | |||
47ed4da9e9 | |||
c4b1dd175d | |||
d09deb3147 |
@@ -3010,6 +3010,22 @@ def km_clip_dopesheet_editor(_params):
|
||||
|
||||
return keymap
|
||||
|
||||
def km_spreadsheet_generic(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Spreadsheet Generic",
|
||||
{"space_type": 'SPREADSHEET', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
*_template_space_region_type_toggle(
|
||||
sidebar_key={"type": 'N', "value": 'PRESS'},
|
||||
),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Animation
|
||||
@@ -7067,6 +7083,7 @@ def generate_keymaps(params=None):
|
||||
km_image(params),
|
||||
km_node_generic(params),
|
||||
km_node_editor(params),
|
||||
km_spreadsheet_generic(params),
|
||||
km_info(params),
|
||||
km_file_browser(params),
|
||||
km_file_browser_main(params),
|
||||
|
@@ -2144,6 +2144,23 @@ def km_clip_dopesheet_editor(_params):
|
||||
return keymap
|
||||
|
||||
|
||||
def km_spreadsheet_generic(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Spreadsheet Generic",
|
||||
{"space_type": 'SPREADSHEET', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
*_template_space_region_type_toggle(
|
||||
sidebar_key={"type": 'N', "value": 'PRESS'},
|
||||
),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Animation
|
||||
|
||||
@@ -4067,6 +4084,7 @@ def generate_keymaps_impl(params=None):
|
||||
km_image(params),
|
||||
km_node_generic(params),
|
||||
km_node_editor(params),
|
||||
km_spreadsheet_generic(params),
|
||||
km_info(params),
|
||||
km_file_browser(params),
|
||||
km_file_browser_main(params),
|
||||
|
@@ -59,9 +59,12 @@ class SPREADSHEET_HT_header(bpy.types.Header):
|
||||
layout.operator("spreadsheet.toggle_pin", text="", icon=pin_icon, emboss=False)
|
||||
|
||||
layout.separator_spacer()
|
||||
|
||||
if isinstance(obj, bpy.types.Object) and obj.mode == 'EDIT':
|
||||
layout.prop(space, "show_only_selected", text="Selected Only")
|
||||
|
||||
row = layout.row(align=True)
|
||||
sub = row.row(align=True)
|
||||
sub.active = self.selection_filter_enabled(space)
|
||||
sub.prop(space, "show_only_selected", text="")
|
||||
row.prop(space, "use_filter", toggle=True, icon='FILTER', icon_only=True)
|
||||
|
||||
def draw_without_context_path(self, layout):
|
||||
layout.label(text="No active context")
|
||||
@@ -102,6 +105,17 @@ class SPREADSHEET_HT_header(bpy.types.Header):
|
||||
def draw_spreadsheet_context_path_icon(self, layout, space, icon='RIGHTARROW_THIN'):
|
||||
layout.prop(space, "display_context_path_collapsed", icon_only=True, emboss=False, icon=icon)
|
||||
|
||||
def selection_filter_enabled(self, space):
|
||||
root_context = space.context_path[0]
|
||||
if root_context.type != 'OBJECT':
|
||||
return False
|
||||
obj = root_context.object
|
||||
if obj is None:
|
||||
return False
|
||||
if obj.type != 'MESH' or obj.mode != 'EDIT':
|
||||
return False
|
||||
return True
|
||||
|
||||
classes = (
|
||||
SPREADSHEET_HT_header,
|
||||
)
|
||||
|
@@ -1357,12 +1357,20 @@ static void write_area(BlendWriter *writer, ScrArea *area)
|
||||
}
|
||||
else if (sl->spacetype == SPACE_SPREADSHEET) {
|
||||
BLO_write_struct(writer, SpaceSpreadsheet, sl);
|
||||
|
||||
SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
|
||||
|
||||
LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, &sspreadsheet->row_filters) {
|
||||
BLO_write_struct(writer, SpreadsheetRowFilter, row_filter);
|
||||
BLO_write_string(writer, row_filter->value_string);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (SpreadsheetColumn *, column, &sspreadsheet->columns) {
|
||||
BLO_write_struct(writer, SpreadsheetColumn, column);
|
||||
BLO_write_struct(writer, SpreadsheetColumnID, column->id);
|
||||
BLO_write_string(writer, column->id->name);
|
||||
/* While the display name is technically runtime data, we write it here, otherwise the row
|
||||
* filters might not now their type if their region draws before the main region. */
|
||||
BLO_write_string(writer, column->display_name);
|
||||
}
|
||||
LISTBASE_FOREACH (SpreadsheetContext *, context, &sspreadsheet->context_path) {
|
||||
switch (context->type) {
|
||||
@@ -1743,11 +1751,17 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area)
|
||||
SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
|
||||
|
||||
sspreadsheet->runtime = NULL;
|
||||
|
||||
BLO_read_list(reader, &sspreadsheet->row_filters);
|
||||
LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, &sspreadsheet->row_filters) {
|
||||
BLO_read_data_address(reader, &row_filter->value_string);
|
||||
}
|
||||
BLO_read_list(reader, &sspreadsheet->columns);
|
||||
LISTBASE_FOREACH (SpreadsheetColumn *, column, &sspreadsheet->columns) {
|
||||
BLO_read_data_address(reader, &column->id);
|
||||
BLO_read_data_address(reader, &column->id->name);
|
||||
/* While the display name is technically runtime data, it is loaded here, otherwise the row
|
||||
* filters might not now their type if their region draws before the main region. */
|
||||
BLO_read_data_address(reader, &column->display_name);
|
||||
}
|
||||
|
||||
BLO_read_list(reader, &sspreadsheet->context_path);
|
||||
|
@@ -2090,5 +2090,23 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
|
||||
/* Add a properties sidebar to the spreadsheet editor. */
|
||||
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
||||
if (sl->spacetype == SPACE_SPREADSHEET) {
|
||||
ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
|
||||
&sl->regionbase;
|
||||
ARegion *new_sidebar = do_versions_add_region_if_not_found(
|
||||
regionbase, RGN_TYPE_UI, "sidebar for spreadsheet", RGN_TYPE_FOOTER);
|
||||
if (new_sidebar != NULL) {
|
||||
new_sidebar->alignment = RGN_ALIGN_RIGHT;
|
||||
new_sidebar->flag |= RGN_FLAG_HIDDEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -317,6 +317,7 @@ bool ED_operator_animview_active(struct bContext *C);
|
||||
bool ED_operator_outliner_active(struct bContext *C);
|
||||
bool ED_operator_outliner_active_no_editobject(struct bContext *C);
|
||||
bool ED_operator_file_active(struct bContext *C);
|
||||
bool ED_operator_spreadsheet_active(struct bContext *C);
|
||||
bool ED_operator_action_active(struct bContext *C);
|
||||
bool ED_operator_buttons_active(struct bContext *C);
|
||||
bool ED_operator_node_active(struct bContext *C);
|
||||
|
@@ -674,7 +674,7 @@ static bool panel_type_context_poll(ARegion *region,
|
||||
const PanelType *panel_type,
|
||||
const char *context)
|
||||
{
|
||||
if (UI_panel_category_is_visible(region)) {
|
||||
if (!BLI_listbase_is_empty(®ion->panels_category)) {
|
||||
return STREQ(panel_type->category, UI_panel_category_active_get(region, false));
|
||||
}
|
||||
|
||||
|
@@ -279,6 +279,11 @@ bool ED_operator_file_active(bContext *C)
|
||||
return ed_spacetype_test(C, SPACE_FILE);
|
||||
}
|
||||
|
||||
bool ED_operator_spreadsheet_active(bContext *C)
|
||||
{
|
||||
return ed_spacetype_test(C, SPACE_SPREADSHEET);
|
||||
}
|
||||
|
||||
bool ED_operator_action_active(bContext *C)
|
||||
{
|
||||
return ed_spacetype_test(C, SPACE_ACTION);
|
||||
|
@@ -20,6 +20,7 @@ set(INC
|
||||
../../blenfont
|
||||
../../blenkernel
|
||||
../../blenlib
|
||||
../../blentranslation
|
||||
../../bmesh
|
||||
../../depsgraph
|
||||
../../functions
|
||||
@@ -40,6 +41,8 @@ set(SRC
|
||||
spreadsheet_draw.cc
|
||||
spreadsheet_layout.cc
|
||||
spreadsheet_ops.cc
|
||||
spreadsheet_row_filter.cc
|
||||
spreadsheet_row_filter_ui.cc
|
||||
|
||||
spreadsheet_context.hh
|
||||
spreadsheet_cell_value.hh
|
||||
@@ -50,6 +53,8 @@ set(SRC
|
||||
spreadsheet_draw.hh
|
||||
spreadsheet_intern.hh
|
||||
spreadsheet_layout.hh
|
||||
spreadsheet_row_filter.hh
|
||||
spreadsheet_row_filter_ui.hh
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
@@ -49,6 +49,8 @@
|
||||
#include "spreadsheet_data_source_geometry.hh"
|
||||
#include "spreadsheet_intern.hh"
|
||||
#include "spreadsheet_layout.hh"
|
||||
#include "spreadsheet_row_filter.hh"
|
||||
#include "spreadsheet_row_filter_ui.hh"
|
||||
|
||||
using namespace blender;
|
||||
using namespace blender::ed::spreadsheet;
|
||||
@@ -59,6 +61,8 @@ static SpaceLink *spreadsheet_create(const ScrArea *UNUSED(area), const Scene *U
|
||||
"spreadsheet space");
|
||||
spreadsheet_space->spacetype = SPACE_SPREADSHEET;
|
||||
|
||||
spreadsheet_space->filter_flag = SPREADSHEET_FILTER_ENABLE;
|
||||
|
||||
{
|
||||
/* Header. */
|
||||
ARegion *region = (ARegion *)MEM_callocN(sizeof(ARegion), "spreadsheet header");
|
||||
@@ -75,6 +79,15 @@ static SpaceLink *spreadsheet_create(const ScrArea *UNUSED(area), const Scene *U
|
||||
region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_TOP : RGN_ALIGN_BOTTOM;
|
||||
}
|
||||
|
||||
{
|
||||
/* Properties region. */
|
||||
ARegion *region = (ARegion *)MEM_callocN(sizeof(ARegion), "spreadsheet right region");
|
||||
BLI_addtail(&spreadsheet_space->regionbase, region);
|
||||
region->regiontype = RGN_TYPE_UI;
|
||||
region->alignment = RGN_ALIGN_RIGHT;
|
||||
region->flag = RGN_FLAG_HIDDEN;
|
||||
}
|
||||
|
||||
{
|
||||
/* Main window. */
|
||||
ARegion *region = (ARegion *)MEM_callocN(sizeof(ARegion), "spreadsheet main region");
|
||||
@@ -88,8 +101,12 @@ static SpaceLink *spreadsheet_create(const ScrArea *UNUSED(area), const Scene *U
|
||||
static void spreadsheet_free(SpaceLink *sl)
|
||||
{
|
||||
SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
|
||||
|
||||
MEM_SAFE_FREE(sspreadsheet->runtime);
|
||||
|
||||
LISTBASE_FOREACH_MUTABLE (SpreadsheetRowFilter *, row_filter, &sspreadsheet->row_filters) {
|
||||
spreadsheet_row_filter_free(row_filter);
|
||||
}
|
||||
LISTBASE_FOREACH_MUTABLE (SpreadsheetColumn *, column, &sspreadsheet->columns) {
|
||||
spreadsheet_column_free(column);
|
||||
}
|
||||
@@ -113,6 +130,11 @@ static SpaceLink *spreadsheet_duplicate(SpaceLink *sl)
|
||||
SpaceSpreadsheet *sspreadsheet_new = (SpaceSpreadsheet *)MEM_dupallocN(sspreadsheet_old);
|
||||
sspreadsheet_new->runtime = (SpaceSpreadsheet_Runtime *)MEM_dupallocN(sspreadsheet_old->runtime);
|
||||
|
||||
BLI_listbase_clear(&sspreadsheet_new->row_filters);
|
||||
LISTBASE_FOREACH (const SpreadsheetRowFilter *, src_filter, &sspreadsheet_old->row_filters) {
|
||||
SpreadsheetRowFilter *new_filter = spreadsheet_row_filter_copy(src_filter);
|
||||
BLI_addtail(&sspreadsheet_new->row_filters, new_filter);
|
||||
}
|
||||
BLI_listbase_clear(&sspreadsheet_new->columns);
|
||||
LISTBASE_FOREACH (SpreadsheetColumn *, src_column, &sspreadsheet_old->columns) {
|
||||
SpreadsheetColumn *new_column = spreadsheet_column_copy(src_column);
|
||||
@@ -128,8 +150,10 @@ static SpaceLink *spreadsheet_duplicate(SpaceLink *sl)
|
||||
return (SpaceLink *)sspreadsheet_new;
|
||||
}
|
||||
|
||||
static void spreadsheet_keymap(wmKeyConfig *UNUSED(keyconf))
|
||||
static void spreadsheet_keymap(wmKeyConfig *keyconf)
|
||||
{
|
||||
/* Entire editor only. */
|
||||
WM_keymap_ensure(keyconf, "Spreadsheet Generic", SPACE_SPREADSHEET, 0);
|
||||
}
|
||||
|
||||
static void spreadsheet_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
|
||||
@@ -160,8 +184,15 @@ static void spreadsheet_main_region_init(wmWindowManager *wm, ARegion *region)
|
||||
|
||||
UI_view2d_region_reinit(®ion->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
|
||||
|
||||
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0);
|
||||
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
||||
{
|
||||
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0);
|
||||
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
||||
}
|
||||
{
|
||||
wmKeyMap *keymap = WM_keymap_ensure(
|
||||
wm->defaultconf, "Spreadsheet Generic", SPACE_SPREADSHEET, 0);
|
||||
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
||||
}
|
||||
}
|
||||
|
||||
ID *ED_spreadsheet_get_current_id(struct SpaceSpreadsheet *sspreadsheet)
|
||||
@@ -346,24 +377,14 @@ static void spreadsheet_main_region_draw(const bContext *C, ARegion *region)
|
||||
const ColumnValues *values = scope.add(std::move(values_ptr), __func__);
|
||||
const int width = get_column_width_in_pixels(*values);
|
||||
spreadsheet_layout.columns.append({values, width});
|
||||
|
||||
spreadsheet_column_assign_runtime_data(column, values->type(), values->name());
|
||||
}
|
||||
|
||||
const int tot_rows = data_source->tot_rows();
|
||||
spreadsheet_layout.index_column_width = get_index_column_width(tot_rows);
|
||||
spreadsheet_layout.row_indices = IndexRange(tot_rows).as_span();
|
||||
|
||||
if (const GeometryDataSource *geometry_data_source = dynamic_cast<const GeometryDataSource *>(
|
||||
data_source.get())) {
|
||||
Object *object_eval = geometry_data_source->object_eval();
|
||||
Object *object_orig = DEG_get_original_object(object_eval);
|
||||
if (object_orig->type == OB_MESH) {
|
||||
if (object_orig->mode == OB_MODE_EDIT) {
|
||||
if (sspreadsheet->filter_flag & SPREADSHEET_FILTER_SELECTED_ONLY) {
|
||||
spreadsheet_layout.row_indices = geometry_data_source->get_selected_element_indices();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
spreadsheet_layout.row_indices = spreadsheet_filter_rows(
|
||||
*sspreadsheet, spreadsheet_layout, *data_source, scope);
|
||||
|
||||
sspreadsheet->runtime->tot_columns = spreadsheet_layout.columns.size();
|
||||
sspreadsheet->runtime->tot_rows = tot_rows;
|
||||
@@ -372,9 +393,11 @@ static void spreadsheet_main_region_draw(const bContext *C, ARegion *region)
|
||||
std::unique_ptr<SpreadsheetDrawer> drawer = spreadsheet_drawer_from_layout(spreadsheet_layout);
|
||||
draw_spreadsheet_in_region(C, region, *drawer);
|
||||
|
||||
/* Tag footer for redraw, because the main region updates data for the footer. */
|
||||
/* Tag other regions for redraw, because the main region updates data for them. */
|
||||
ARegion *footer = BKE_area_find_region_type(CTX_wm_area(C), RGN_TYPE_FOOTER);
|
||||
ED_region_tag_redraw(footer);
|
||||
ARegion *sidebar = BKE_area_find_region_type(CTX_wm_area(C), RGN_TYPE_UI);
|
||||
ED_region_tag_redraw(sidebar);
|
||||
}
|
||||
|
||||
static void spreadsheet_main_region_listener(const wmRegionListenerParams *params)
|
||||
@@ -511,6 +534,24 @@ static void spreadsheet_footer_region_listener(const wmRegionListenerParams *UNU
|
||||
{
|
||||
}
|
||||
|
||||
static void spreadsheet_sidebar_init(wmWindowManager *wm, ARegion *region)
|
||||
{
|
||||
UI_panel_category_active_set_default(region, "Filters");
|
||||
ED_region_panels_init(wm, region);
|
||||
|
||||
wmKeyMap *keymap = WM_keymap_ensure(
|
||||
wm->defaultconf, "Spreadsheet Generic", SPACE_SPREADSHEET, 0);
|
||||
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
||||
}
|
||||
|
||||
static void spreadsheet_right_region_free(ARegion *UNUSED(region))
|
||||
{
|
||||
}
|
||||
|
||||
static void spreadsheet_right_region_listener(const wmRegionListenerParams *UNUSED(params))
|
||||
{
|
||||
}
|
||||
|
||||
void ED_spacetype_spreadsheet(void)
|
||||
{
|
||||
SpaceType *st = (SpaceType *)MEM_callocN(sizeof(SpaceType), "spacetype spreadsheet");
|
||||
@@ -563,5 +604,20 @@ void ED_spacetype_spreadsheet(void)
|
||||
art->listener = spreadsheet_footer_region_listener;
|
||||
BLI_addhead(&st->regiontypes, art);
|
||||
|
||||
/* regions: right panel buttons */
|
||||
art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spacetype spreadsheet right region");
|
||||
art->regionid = RGN_TYPE_UI;
|
||||
art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
|
||||
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
|
||||
|
||||
art->init = spreadsheet_sidebar_init;
|
||||
art->layout = ED_region_panels_layout;
|
||||
art->draw = ED_region_panels_draw;
|
||||
art->free = spreadsheet_right_region_free;
|
||||
art->listener = spreadsheet_right_region_listener;
|
||||
BLI_addhead(&st->regiontypes, art);
|
||||
|
||||
register_row_filter_panels(*art);
|
||||
|
||||
BKE_spacetype_register(st);
|
||||
}
|
||||
|
@@ -56,16 +56,29 @@ SpreadsheetColumn *spreadsheet_column_new(SpreadsheetColumnID *column_id)
|
||||
return column;
|
||||
}
|
||||
|
||||
void spreadsheet_column_assign_runtime_data(SpreadsheetColumn *column,
|
||||
const eSpreadsheetColumnValueType data_type,
|
||||
const StringRefNull display_name)
|
||||
{
|
||||
column->data_type = data_type;
|
||||
MEM_SAFE_FREE(column->display_name);
|
||||
column->display_name = BLI_strdup(display_name.c_str());
|
||||
}
|
||||
|
||||
SpreadsheetColumn *spreadsheet_column_copy(const SpreadsheetColumn *src_column)
|
||||
{
|
||||
SpreadsheetColumnID *new_column_id = spreadsheet_column_id_copy(src_column->id);
|
||||
SpreadsheetColumn *new_column = spreadsheet_column_new(new_column_id);
|
||||
if (src_column->display_name != nullptr) {
|
||||
new_column->display_name = BLI_strdup(src_column->display_name);
|
||||
}
|
||||
return new_column;
|
||||
}
|
||||
|
||||
void spreadsheet_column_free(SpreadsheetColumn *column)
|
||||
{
|
||||
spreadsheet_column_id_free(column->id);
|
||||
MEM_SAFE_FREE(column->display_name);
|
||||
MEM_freeN(column);
|
||||
}
|
||||
|
||||
|
@@ -43,6 +43,9 @@ void spreadsheet_column_id_free(SpreadsheetColumnID *column_id);
|
||||
|
||||
SpreadsheetColumn *spreadsheet_column_new(SpreadsheetColumnID *column_id);
|
||||
SpreadsheetColumn *spreadsheet_column_copy(const SpreadsheetColumn *src_column);
|
||||
void spreadsheet_column_assign_runtime_data(SpreadsheetColumn *column,
|
||||
const eSpreadsheetColumnValueType data_type,
|
||||
const StringRefNull display_name);
|
||||
void spreadsheet_column_free(SpreadsheetColumn *column);
|
||||
|
||||
} // namespace blender::ed::spreadsheet
|
||||
|
@@ -16,6 +16,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BLI_string_ref.hh"
|
||||
|
||||
#include "spreadsheet_cell_value.hh"
|
||||
@@ -28,11 +30,13 @@ namespace blender::ed::spreadsheet {
|
||||
*/
|
||||
class ColumnValues {
|
||||
protected:
|
||||
eSpreadsheetColumnValueType type_;
|
||||
std::string name_;
|
||||
int size_;
|
||||
|
||||
public:
|
||||
ColumnValues(std::string name, const int size) : name_(std::move(name)), size_(size)
|
||||
ColumnValues(const eSpreadsheetColumnValueType type, std::string name, const int size)
|
||||
: type_(type), name_(std::move(name)), size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -40,6 +44,11 @@ class ColumnValues {
|
||||
|
||||
virtual void get_value(int index, CellValue &r_cell_value) const = 0;
|
||||
|
||||
eSpreadsheetColumnValueType type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
StringRefNull name() const
|
||||
{
|
||||
return name_;
|
||||
@@ -60,8 +69,11 @@ template<typename GetValueF> class LambdaColumnValues : public ColumnValues {
|
||||
GetValueF get_value_;
|
||||
|
||||
public:
|
||||
LambdaColumnValues(std::string name, int size, GetValueF get_value)
|
||||
: ColumnValues(std::move(name), size), get_value_(std::move(get_value))
|
||||
LambdaColumnValues(const eSpreadsheetColumnValueType type,
|
||||
std::string name,
|
||||
int size,
|
||||
GetValueF get_value)
|
||||
: ColumnValues(type, std::move(name), size), get_value_(std::move(get_value))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -73,13 +85,14 @@ template<typename GetValueF> class LambdaColumnValues : public ColumnValues {
|
||||
|
||||
/* Utility function that simplifies creating a spreadsheet column from a lambda function. */
|
||||
template<typename GetValueF>
|
||||
std::unique_ptr<ColumnValues> column_values_from_function(std::string name,
|
||||
std::unique_ptr<ColumnValues> column_values_from_function(const eSpreadsheetColumnValueType type,
|
||||
std::string name,
|
||||
const int size,
|
||||
GetValueF get_value,
|
||||
const float default_width = 0.0f)
|
||||
{
|
||||
std::unique_ptr<ColumnValues> column_values = std::make_unique<LambdaColumnValues<GetValueF>>(
|
||||
std::move(name), size, std::move(get_value));
|
||||
type, std::move(name), size, std::move(get_value));
|
||||
column_values->default_width = default_width;
|
||||
return column_values;
|
||||
}
|
||||
|
@@ -53,6 +53,15 @@ class DataSource {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff the data source has the ability to limit visible rows
|
||||
* by user interface selection status.
|
||||
*/
|
||||
virtual bool has_selection_filter() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of rows in columns returned by #get_column_values.
|
||||
*/
|
||||
|
@@ -69,28 +69,35 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
const CustomDataType type = bke::cpp_type_to_custom_data_type(varray->type());
|
||||
switch (type) {
|
||||
case CD_PROP_FLOAT:
|
||||
return column_values_from_function(
|
||||
column_id.name, domain_size, [varray](int index, CellValue &r_cell_value) {
|
||||
float value;
|
||||
varray->get(index, &value);
|
||||
r_cell_value.value_float = value;
|
||||
});
|
||||
return column_values_from_function(SPREADSHEET_VALUE_TYPE_FLOAT,
|
||||
column_id.name,
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
float value;
|
||||
varray->get(index, &value);
|
||||
r_cell_value.value_float = value;
|
||||
});
|
||||
case CD_PROP_INT32:
|
||||
return column_values_from_function(
|
||||
column_id.name, domain_size, [varray](int index, CellValue &r_cell_value) {
|
||||
int value;
|
||||
varray->get(index, &value);
|
||||
r_cell_value.value_int = value;
|
||||
});
|
||||
return column_values_from_function(SPREADSHEET_VALUE_TYPE_INT32,
|
||||
column_id.name,
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
int value;
|
||||
varray->get(index, &value);
|
||||
r_cell_value.value_int = value;
|
||||
});
|
||||
case CD_PROP_BOOL:
|
||||
return column_values_from_function(
|
||||
column_id.name, domain_size, [varray](int index, CellValue &r_cell_value) {
|
||||
bool value;
|
||||
varray->get(index, &value);
|
||||
r_cell_value.value_bool = value;
|
||||
});
|
||||
return column_values_from_function(SPREADSHEET_VALUE_TYPE_BOOL,
|
||||
column_id.name,
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
bool value;
|
||||
varray->get(index, &value);
|
||||
r_cell_value.value_bool = value;
|
||||
});
|
||||
case CD_PROP_FLOAT2: {
|
||||
return column_values_from_function(
|
||||
SPREADSHEET_VALUE_TYPE_FLOAT2,
|
||||
column_id.name,
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
@@ -102,6 +109,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
}
|
||||
case CD_PROP_FLOAT3: {
|
||||
return column_values_from_function(
|
||||
SPREADSHEET_VALUE_TYPE_FLOAT3,
|
||||
column_id.name,
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
@@ -113,6 +121,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
}
|
||||
case CD_PROP_COLOR: {
|
||||
return column_values_from_function(
|
||||
SPREADSHEET_VALUE_TYPE_COLOR,
|
||||
column_id.name,
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
@@ -137,55 +146,63 @@ using IsVertexSelectedFn = FunctionRef<bool(int vertex_index)>;
|
||||
|
||||
static void get_selected_vertex_indices(const Mesh &mesh,
|
||||
const IsVertexSelectedFn is_vertex_selected_fn,
|
||||
Vector<int64_t> &r_vertex_indices)
|
||||
MutableSpan<bool> selection)
|
||||
{
|
||||
for (const int i : IndexRange(mesh.totvert)) {
|
||||
if (is_vertex_selected_fn(i)) {
|
||||
r_vertex_indices.append(i);
|
||||
if (!selection[i]) {
|
||||
continue;
|
||||
}
|
||||
if (!is_vertex_selected_fn(i)) {
|
||||
selection[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void get_selected_corner_indices(const Mesh &mesh,
|
||||
const IsVertexSelectedFn is_vertex_selected_fn,
|
||||
Vector<int64_t> &r_corner_indices)
|
||||
MutableSpan<bool> selection)
|
||||
{
|
||||
for (const int i : IndexRange(mesh.totloop)) {
|
||||
const MLoop &loop = mesh.mloop[i];
|
||||
if (is_vertex_selected_fn(loop.v)) {
|
||||
r_corner_indices.append(i);
|
||||
if (!selection[i]) {
|
||||
continue;
|
||||
}
|
||||
if (!is_vertex_selected_fn(loop.v)) {
|
||||
selection[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void get_selected_face_indices(const Mesh &mesh,
|
||||
const IsVertexSelectedFn is_vertex_selected_fn,
|
||||
Vector<int64_t> &r_face_indices)
|
||||
MutableSpan<bool> selection)
|
||||
{
|
||||
for (const int poly_index : IndexRange(mesh.totpoly)) {
|
||||
if (!selection[poly_index]) {
|
||||
continue;
|
||||
}
|
||||
const MPoly &poly = mesh.mpoly[poly_index];
|
||||
bool is_selected = true;
|
||||
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
|
||||
const MLoop &loop = mesh.mloop[loop_index];
|
||||
if (!is_vertex_selected_fn(loop.v)) {
|
||||
is_selected = false;
|
||||
selection[poly_index] = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_selected) {
|
||||
r_face_indices.append(poly_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void get_selected_edge_indices(const Mesh &mesh,
|
||||
const IsVertexSelectedFn is_vertex_selected_fn,
|
||||
Vector<int64_t> &r_edge_indices)
|
||||
MutableSpan<bool> selection)
|
||||
{
|
||||
for (const int i : IndexRange(mesh.totedge)) {
|
||||
if (!selection[i]) {
|
||||
continue;
|
||||
}
|
||||
const MEdge &edge = mesh.medge[i];
|
||||
if (is_vertex_selected_fn(edge.v1) && is_vertex_selected_fn(edge.v2)) {
|
||||
r_edge_indices.append(i);
|
||||
if (!is_vertex_selected_fn(edge.v1) || !is_vertex_selected_fn(edge.v2)) {
|
||||
selection[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -193,30 +210,40 @@ static void get_selected_edge_indices(const Mesh &mesh,
|
||||
static void get_selected_indices_on_domain(const Mesh &mesh,
|
||||
const AttributeDomain domain,
|
||||
const IsVertexSelectedFn is_vertex_selected_fn,
|
||||
Vector<int64_t> &r_indices)
|
||||
MutableSpan<bool> selection)
|
||||
{
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return get_selected_vertex_indices(mesh, is_vertex_selected_fn, r_indices);
|
||||
return get_selected_vertex_indices(mesh, is_vertex_selected_fn, selection);
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return get_selected_face_indices(mesh, is_vertex_selected_fn, r_indices);
|
||||
return get_selected_face_indices(mesh, is_vertex_selected_fn, selection);
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
return get_selected_corner_indices(mesh, is_vertex_selected_fn, r_indices);
|
||||
return get_selected_corner_indices(mesh, is_vertex_selected_fn, selection);
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return get_selected_edge_indices(mesh, is_vertex_selected_fn, r_indices);
|
||||
return get_selected_edge_indices(mesh, is_vertex_selected_fn, selection);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Span<int64_t> GeometryDataSource::get_selected_element_indices() const
|
||||
bool GeometryDataSource::has_selection_filter() const
|
||||
{
|
||||
Object *object_orig = DEG_get_original_object(object_eval_);
|
||||
if (object_orig->type == OB_MESH) {
|
||||
if (object_orig->mode == OB_MODE_EDIT) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GeometryDataSource::apply_selection_filter(MutableSpan<bool> rows_included) const
|
||||
{
|
||||
std::lock_guard lock{mutex_};
|
||||
|
||||
BLI_assert(object_eval_->mode == OB_MODE_EDIT);
|
||||
BLI_assert(component_->type() == GEO_COMPONENT_TYPE_MESH);
|
||||
Object *object_orig = DEG_get_original_object(object_eval_);
|
||||
Vector<int64_t> &indices = scope_.construct<Vector<int64_t>>(__func__);
|
||||
const MeshComponent *mesh_component = static_cast<const MeshComponent *>(component_);
|
||||
const Mesh *mesh_eval = mesh_component->get_for_read();
|
||||
Mesh *mesh_orig = (Mesh *)object_orig->data;
|
||||
@@ -237,7 +264,7 @@ Span<int64_t> GeometryDataSource::get_selected_element_indices() const
|
||||
BMVert *vert = bm->vtable[i_orig];
|
||||
return BM_elem_flag_test(vert, BM_ELEM_SELECT);
|
||||
};
|
||||
get_selected_indices_on_domain(*mesh_eval, domain_, is_vertex_selected, indices);
|
||||
get_selected_indices_on_domain(*mesh_eval, domain_, is_vertex_selected, rows_included);
|
||||
}
|
||||
else if (mesh_eval->totvert == bm->totvert) {
|
||||
/* Use a simple heuristic to match original vertices to evaluated ones. */
|
||||
@@ -245,10 +272,8 @@ Span<int64_t> GeometryDataSource::get_selected_element_indices() const
|
||||
BMVert *vert = bm->vtable[vertex_index];
|
||||
return BM_elem_flag_test(vert, BM_ELEM_SELECT);
|
||||
};
|
||||
get_selected_indices_on_domain(*mesh_eval, domain_, is_vertex_selected, indices);
|
||||
get_selected_indices_on_domain(*mesh_eval, domain_, is_vertex_selected, rows_included);
|
||||
}
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
void InstancesDataSource::foreach_default_column_ids(
|
||||
@@ -279,7 +304,10 @@ std::unique_ptr<ColumnValues> InstancesDataSource::get_column_values(
|
||||
Span<int> reference_handles = component_->instance_reference_handles();
|
||||
Span<InstanceReference> references = component_->references();
|
||||
std::unique_ptr<ColumnValues> values = column_values_from_function(
|
||||
"Name", size, [reference_handles, references](int index, CellValue &r_cell_value) {
|
||||
SPREADSHEET_VALUE_TYPE_INSTANCES,
|
||||
"Name",
|
||||
size,
|
||||
[reference_handles, references](int index, CellValue &r_cell_value) {
|
||||
const InstanceReference &reference = references[reference_handles[index]];
|
||||
switch (reference.type()) {
|
||||
case InstanceReference::Type::Object: {
|
||||
@@ -303,6 +331,7 @@ std::unique_ptr<ColumnValues> InstancesDataSource::get_column_values(
|
||||
Span<float4x4> transforms = component_->instance_transforms();
|
||||
if (STREQ(column_id.name, "Position")) {
|
||||
return column_values_from_function(
|
||||
SPREADSHEET_VALUE_TYPE_FLOAT3,
|
||||
column_id.name,
|
||||
size,
|
||||
[transforms](int index, CellValue &r_cell_value) {
|
||||
@@ -312,6 +341,7 @@ std::unique_ptr<ColumnValues> InstancesDataSource::get_column_values(
|
||||
}
|
||||
if (STREQ(column_id.name, "Rotation")) {
|
||||
return column_values_from_function(
|
||||
SPREADSHEET_VALUE_TYPE_FLOAT3,
|
||||
column_id.name,
|
||||
size,
|
||||
[transforms](int index, CellValue &r_cell_value) {
|
||||
@@ -321,6 +351,7 @@ std::unique_ptr<ColumnValues> InstancesDataSource::get_column_values(
|
||||
}
|
||||
if (STREQ(column_id.name, "Scale")) {
|
||||
return column_values_from_function(
|
||||
SPREADSHEET_VALUE_TYPE_FLOAT3,
|
||||
column_id.name,
|
||||
size,
|
||||
[transforms](int index, CellValue &r_cell_value) {
|
||||
@@ -332,6 +363,7 @@ std::unique_ptr<ColumnValues> InstancesDataSource::get_column_values(
|
||||
if (STREQ(column_id.name, "ID")) {
|
||||
/* Make the column a bit wider by default, since the IDs tend to be large numbers. */
|
||||
return column_values_from_function(
|
||||
SPREADSHEET_VALUE_TYPE_INT32,
|
||||
column_id.name,
|
||||
size,
|
||||
[ids](int index, CellValue &r_cell_value) { r_cell_value.value_int = ids[index]; },
|
||||
|
@@ -58,7 +58,8 @@ class GeometryDataSource : public DataSource {
|
||||
return object_eval_;
|
||||
}
|
||||
|
||||
Span<int64_t> get_selected_element_indices() const;
|
||||
bool has_selection_filter() const override;
|
||||
void apply_selection_filter(MutableSpan<bool> rows_included) const;
|
||||
|
||||
void foreach_default_column_ids(
|
||||
FunctionRef<void(const SpreadsheetColumnID &)> fn) const override;
|
||||
|
@@ -14,8 +14,83 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "spreadsheet_intern.hh"
|
||||
#include "spreadsheet_row_filter.hh"
|
||||
|
||||
using namespace blender::ed::spreadsheet;
|
||||
|
||||
static int row_filter_add_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
|
||||
|
||||
SpreadsheetRowFilter *row_filter = spreadsheet_row_filter_new();
|
||||
BLI_addtail(&sspreadsheet->row_filters, row_filter);
|
||||
|
||||
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_SPREADSHEET, sspreadsheet);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void SPREADSHEET_OT_add_row_filter_rule(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Add Row Filter";
|
||||
ot->description = "Add a filter to remove rows from the displayed data";
|
||||
ot->idname = "SPREADSHEET_OT_add_row_filter_rule";
|
||||
|
||||
ot->exec = row_filter_add_exec;
|
||||
ot->poll = ED_operator_spreadsheet_active;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
static int row_filter_remove_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
|
||||
|
||||
SpreadsheetRowFilter *row_filter = (SpreadsheetRowFilter *)BLI_findlink(
|
||||
&sspreadsheet->row_filters, RNA_int_get(op->ptr, "index"));
|
||||
if (row_filter == nullptr) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
BLI_remlink(&sspreadsheet->row_filters, row_filter);
|
||||
spreadsheet_row_filter_free(row_filter);
|
||||
|
||||
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_SPREADSHEET, sspreadsheet);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void SPREADSHEET_OT_remove_row_filter_rule(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Remove Row Filter";
|
||||
ot->description = "Remove a row filter from the rules";
|
||||
ot->idname = "SPREADSHEET_OT_remove_row_filter_rule";
|
||||
|
||||
ot->exec = row_filter_remove_exec;
|
||||
ot->poll = ED_operator_spreadsheet_active;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
|
||||
}
|
||||
|
||||
void spreadsheet_operatortypes()
|
||||
{
|
||||
WM_operatortype_append(SPREADSHEET_OT_add_row_filter_rule);
|
||||
WM_operatortype_append(SPREADSHEET_OT_remove_row_filter_rule);
|
||||
}
|
||||
|
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
* 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 <cstring>
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "DNA_collection_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "spreadsheet_intern.hh"
|
||||
|
||||
#include "spreadsheet_data_source_geometry.hh"
|
||||
#include "spreadsheet_intern.hh"
|
||||
#include "spreadsheet_layout.hh"
|
||||
#include "spreadsheet_row_filter.hh"
|
||||
|
||||
namespace blender::ed::spreadsheet {
|
||||
|
||||
template<typename OperationFn>
|
||||
static void apply_filter_operation(const ColumnValues &values,
|
||||
OperationFn check_fn,
|
||||
MutableSpan<bool> rows_included)
|
||||
{
|
||||
for (const int i : rows_included.index_range()) {
|
||||
if (!rows_included[i]) {
|
||||
continue;
|
||||
}
|
||||
CellValue cell_value;
|
||||
values.get_value(i, cell_value);
|
||||
if (!check_fn(cell_value)) {
|
||||
rows_included[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void apply_row_filter(const SpreadsheetLayout &spreadsheet_layout,
|
||||
const SpreadsheetRowFilter &row_filter,
|
||||
MutableSpan<bool> rows_included)
|
||||
{
|
||||
for (const ColumnLayout &column : spreadsheet_layout.columns) {
|
||||
const ColumnValues &values = *column.values;
|
||||
if (values.name() != row_filter.column_name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (values.type()) {
|
||||
case SPREADSHEET_VALUE_TYPE_INT32: {
|
||||
const int value = row_filter.value_int;
|
||||
switch (row_filter.operation) {
|
||||
case SPREADSHEET_ROW_FILTER_EQUAL: {
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value](const CellValue &cell_value) -> bool {
|
||||
return *cell_value.value_int == value;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_ROW_FILTER_GREATER: {
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value](const CellValue &cell_value) -> bool {
|
||||
return *cell_value.value_int > value;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_ROW_FILTER_LESS: {
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value](const CellValue &cell_value) -> bool {
|
||||
return *cell_value.value_int < value;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT: {
|
||||
const float value = row_filter.value_float;
|
||||
switch (row_filter.operation) {
|
||||
case SPREADSHEET_ROW_FILTER_EQUAL: {
|
||||
const float threshold = row_filter.threshold;
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value, threshold](const CellValue &cell_value) -> bool {
|
||||
return std::abs(*cell_value.value_float - value) < threshold;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_ROW_FILTER_GREATER: {
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value](const CellValue &cell_value) -> bool {
|
||||
return *cell_value.value_float > value;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_ROW_FILTER_LESS: {
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value](const CellValue &cell_value) -> bool {
|
||||
return *cell_value.value_float < value;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT2: {
|
||||
const float2 value = row_filter.value_float3;
|
||||
switch (row_filter.operation) {
|
||||
case SPREADSHEET_ROW_FILTER_EQUAL: {
|
||||
const float threshold_squared = row_filter.threshold * row_filter.threshold;
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value, threshold_squared](const CellValue &cell_value) -> bool {
|
||||
return float2::distance_squared(*cell_value.value_float2, value) <
|
||||
threshold_squared;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_ROW_FILTER_GREATER: {
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value](const CellValue &cell_value) -> bool {
|
||||
return cell_value.value_float2->x > value.x &&
|
||||
cell_value.value_float2->y > value.y;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_ROW_FILTER_LESS: {
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value](const CellValue &cell_value) -> bool {
|
||||
return cell_value.value_float2->x < value.x &&
|
||||
cell_value.value_float2->y < value.y;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT3: {
|
||||
const float3 value = row_filter.value_float3;
|
||||
switch (row_filter.operation) {
|
||||
case SPREADSHEET_ROW_FILTER_EQUAL: {
|
||||
const float threshold_squared = row_filter.threshold * row_filter.threshold;
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value, threshold_squared](const CellValue &cell_value) -> bool {
|
||||
return float3::distance_squared(*cell_value.value_float3, value) <
|
||||
threshold_squared;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_ROW_FILTER_GREATER: {
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value](const CellValue &cell_value) -> bool {
|
||||
return cell_value.value_float3->x > value.x &&
|
||||
cell_value.value_float3->y > value.y &&
|
||||
cell_value.value_float3->z > value.z;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_ROW_FILTER_LESS: {
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value](const CellValue &cell_value) -> bool {
|
||||
return cell_value.value_float3->x < value.x &&
|
||||
cell_value.value_float3->y < value.y &&
|
||||
cell_value.value_float3->z < value.z;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_COLOR: {
|
||||
const ColorGeometry4f value = row_filter.value_color;
|
||||
switch (row_filter.operation) {
|
||||
case SPREADSHEET_ROW_FILTER_EQUAL: {
|
||||
const float threshold_squared = row_filter.threshold * row_filter.threshold;
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value, threshold_squared](const CellValue &cell_value) -> bool {
|
||||
return len_squared_v4v4(value, *cell_value.value_color) < threshold_squared;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_BOOL: {
|
||||
const bool value = (row_filter.flag & SPREADSHEET_ROW_FILTER_BOOL_VALUE) != 0;
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value](const CellValue &cell_value) -> bool {
|
||||
return *cell_value.value_bool == value;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_INSTANCES: {
|
||||
const StringRef value = row_filter.value_string;
|
||||
apply_filter_operation(
|
||||
values,
|
||||
[value](const CellValue &cell_value) -> bool {
|
||||
const ID *id = nullptr;
|
||||
if (cell_value.value_object) {
|
||||
id = &cell_value.value_object->object->id;
|
||||
}
|
||||
else if (cell_value.value_collection) {
|
||||
id = &cell_value.value_collection->collection->id;
|
||||
}
|
||||
if (id == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return value == id->name + 2;
|
||||
},
|
||||
rows_included);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Only one column should have this name. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void index_vector_from_bools(Span<bool> selection, Vector<int64_t> &indices)
|
||||
{
|
||||
for (const int i : selection.index_range()) {
|
||||
if (selection[i]) {
|
||||
indices.append(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool use_row_filters(const SpaceSpreadsheet &sspreadsheet)
|
||||
{
|
||||
if (!(sspreadsheet.filter_flag & SPREADSHEET_FILTER_ENABLE)) {
|
||||
return false;
|
||||
}
|
||||
if (BLI_listbase_is_empty(&sspreadsheet.row_filters)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool use_selection_filter(const SpaceSpreadsheet &sspreadsheet,
|
||||
const DataSource &data_source)
|
||||
{
|
||||
if (!(sspreadsheet.filter_flag & SPREADSHEET_FILTER_SELECTED_ONLY)) {
|
||||
return false;
|
||||
}
|
||||
if (!data_source.has_selection_filter()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Span<int64_t> spreadsheet_filter_rows(const SpaceSpreadsheet &sspreadsheet,
|
||||
const SpreadsheetLayout &spreadsheet_layout,
|
||||
const DataSource &data_source,
|
||||
ResourceScope &scope)
|
||||
{
|
||||
const int tot_rows = data_source.tot_rows();
|
||||
|
||||
const bool use_selection = use_selection_filter(sspreadsheet, data_source);
|
||||
const bool use_filters = use_row_filters(sspreadsheet);
|
||||
|
||||
/* Avoid allocating an array if no row filtering is necessary. */
|
||||
if (!(use_filters || use_selection)) {
|
||||
return IndexRange(tot_rows).as_span();
|
||||
}
|
||||
|
||||
Array<bool> rows_included(tot_rows, true);
|
||||
|
||||
if (use_filters) {
|
||||
LISTBASE_FOREACH (const SpreadsheetRowFilter *, row_filter, &sspreadsheet.row_filters) {
|
||||
if (row_filter->flag & SPREADSHEET_ROW_FILTER_ENABLED) {
|
||||
apply_row_filter(spreadsheet_layout, *row_filter, rows_included);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (use_selection) {
|
||||
const GeometryDataSource *geometry_data_source = dynamic_cast<const GeometryDataSource *>(
|
||||
&data_source);
|
||||
geometry_data_source->apply_selection_filter(rows_included);
|
||||
}
|
||||
|
||||
Vector<int64_t> &indices = scope.construct<Vector<int64_t>>(__func__);
|
||||
index_vector_from_bools(rows_included, indices);
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
SpreadsheetRowFilter *spreadsheet_row_filter_new()
|
||||
{
|
||||
SpreadsheetRowFilter *row_filter = (SpreadsheetRowFilter *)MEM_callocN(
|
||||
sizeof(SpreadsheetRowFilter), __func__);
|
||||
row_filter->flag = (SPREADSHEET_ROW_FILTER_UI_EXPAND | SPREADSHEET_ROW_FILTER_ENABLED);
|
||||
row_filter->operation = SPREADSHEET_ROW_FILTER_LESS;
|
||||
row_filter->threshold = 0.01f;
|
||||
row_filter->column_name[0] = '\0';
|
||||
|
||||
return row_filter;
|
||||
}
|
||||
|
||||
SpreadsheetRowFilter *spreadsheet_row_filter_copy(const SpreadsheetRowFilter *src_row_filter)
|
||||
{
|
||||
SpreadsheetRowFilter *new_filter = spreadsheet_row_filter_new();
|
||||
|
||||
memcpy(new_filter, src_row_filter, sizeof(SpreadsheetRowFilter));
|
||||
new_filter->next = nullptr;
|
||||
new_filter->prev = nullptr;
|
||||
|
||||
return new_filter;
|
||||
}
|
||||
|
||||
void spreadsheet_row_filter_free(SpreadsheetRowFilter *column)
|
||||
{
|
||||
MEM_freeN(column);
|
||||
}
|
||||
|
||||
} // namespace blender::ed::spreadsheet
|
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 "BLI_resource_scope.hh"
|
||||
|
||||
#include "spreadsheet_data_source.hh"
|
||||
#include "spreadsheet_layout.hh"
|
||||
|
||||
namespace blender::ed::spreadsheet {
|
||||
|
||||
Span<int64_t> spreadsheet_filter_rows(const SpaceSpreadsheet &sspreadsheet,
|
||||
const SpreadsheetLayout &spreadsheet_layout,
|
||||
const DataSource &data_source,
|
||||
ResourceScope &scope);
|
||||
|
||||
SpreadsheetRowFilter *spreadsheet_row_filter_new();
|
||||
SpreadsheetRowFilter *spreadsheet_row_filter_copy(const SpreadsheetRowFilter *src_row_filter);
|
||||
void spreadsheet_row_filter_free(SpreadsheetRowFilter *column);
|
||||
|
||||
} // namespace blender::ed::spreadsheet
|
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* 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 <cstring>
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_ref.hh"
|
||||
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "spreadsheet_column.hh"
|
||||
#include "spreadsheet_intern.hh"
|
||||
#include "spreadsheet_row_filter.hh"
|
||||
#include "spreadsheet_row_filter_ui.hh"
|
||||
|
||||
using namespace blender;
|
||||
using namespace blender::ed::spreadsheet;
|
||||
|
||||
static void filter_panel_id_fn(void *UNUSED(row_filter_v), char *r_name)
|
||||
{
|
||||
/* All row filters use the same panel ID. */
|
||||
BLI_snprintf(r_name, BKE_ST_MAXNAME, "SPREADSHEET_PT_filter");
|
||||
}
|
||||
|
||||
static std::string operation_string(const eSpreadsheetColumnValueType data_type,
|
||||
const eSpreadsheetFilterOperation operation)
|
||||
{
|
||||
if (ELEM(data_type,
|
||||
SPREADSHEET_VALUE_TYPE_BOOL,
|
||||
SPREADSHEET_VALUE_TYPE_INSTANCES,
|
||||
SPREADSHEET_VALUE_TYPE_COLOR)) {
|
||||
return "==";
|
||||
}
|
||||
|
||||
switch (operation) {
|
||||
case SPREADSHEET_ROW_FILTER_EQUAL:
|
||||
return "==";
|
||||
case SPREADSHEET_ROW_FILTER_GREATER:
|
||||
return ">";
|
||||
case SPREADSHEET_ROW_FILTER_LESS:
|
||||
return "<";
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
return "";
|
||||
}
|
||||
|
||||
static std::string value_string(const SpreadsheetRowFilter &row_filter,
|
||||
const eSpreadsheetColumnValueType data_type)
|
||||
{
|
||||
switch (data_type) {
|
||||
case SPREADSHEET_VALUE_TYPE_INT32:
|
||||
return std::to_string(row_filter.value_int);
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT: {
|
||||
std::ostringstream result;
|
||||
result.precision(3);
|
||||
result << std::fixed << row_filter.value_float;
|
||||
return result.str();
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT2: {
|
||||
std::ostringstream result;
|
||||
result.precision(3);
|
||||
result << std::fixed << "(" << row_filter.value_float2[0] << ", "
|
||||
<< row_filter.value_float2[1] << ")";
|
||||
return result.str();
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT3: {
|
||||
std::ostringstream result;
|
||||
result.precision(3);
|
||||
result << std::fixed << "(" << row_filter.value_float3[0] << ", "
|
||||
<< row_filter.value_float3[1] << ", " << row_filter.value_float3[2] << ")";
|
||||
return result.str();
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_BOOL:
|
||||
return (row_filter.flag & SPREADSHEET_ROW_FILTER_BOOL_VALUE) ? IFACE_("True") :
|
||||
IFACE_("False");
|
||||
case SPREADSHEET_VALUE_TYPE_INSTANCES:
|
||||
if (row_filter.value_string != nullptr) {
|
||||
return row_filter.value_string;
|
||||
}
|
||||
return "";
|
||||
case SPREADSHEET_VALUE_TYPE_COLOR:
|
||||
std::ostringstream result;
|
||||
result.precision(3);
|
||||
result << std::fixed << "(" << row_filter.value_color[0] << ", " << row_filter.value_color[1]
|
||||
<< ", " << row_filter.value_color[2] << ", " << row_filter.value_color[3] << ")";
|
||||
return result.str();
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
return "";
|
||||
}
|
||||
|
||||
static SpreadsheetColumn *lookup_visible_column_for_filter(const SpaceSpreadsheet &sspreadsheet,
|
||||
const StringRef column_name)
|
||||
{
|
||||
LISTBASE_FOREACH (SpreadsheetColumn *, column, &sspreadsheet.columns) {
|
||||
if (column->display_name == column_name) {
|
||||
return column;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void spreadsheet_filter_panel_draw_header(const bContext *C, Panel *panel)
|
||||
{
|
||||
uiLayout *layout = panel->layout;
|
||||
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
|
||||
PointerRNA *filter_ptr = UI_panel_custom_data_get(panel);
|
||||
const SpreadsheetRowFilter *filter = (SpreadsheetRowFilter *)filter_ptr->data;
|
||||
const StringRef column_name = filter->column_name;
|
||||
const eSpreadsheetFilterOperation operation = (eSpreadsheetFilterOperation)filter->operation;
|
||||
|
||||
const SpreadsheetColumn *column = lookup_visible_column_for_filter(*sspreadsheet, column_name);
|
||||
if (!(sspreadsheet->filter_flag & SPREADSHEET_FILTER_ENABLE) ||
|
||||
(column == nullptr && !column_name.is_empty())) {
|
||||
uiLayoutSetActive(layout, false);
|
||||
}
|
||||
|
||||
uiLayout *row = uiLayoutRow(layout, true);
|
||||
uiLayoutSetEmboss(row, UI_EMBOSS_NONE);
|
||||
uiItemR(row, filter_ptr, "enabled", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
|
||||
|
||||
if (column_name.is_empty()) {
|
||||
uiItemL(row, IFACE_("Filter"), ICON_NONE);
|
||||
}
|
||||
else if (column == nullptr) {
|
||||
uiItemL(row, column_name.data(), ICON_NONE);
|
||||
}
|
||||
else {
|
||||
const eSpreadsheetColumnValueType data_type = (eSpreadsheetColumnValueType)column->data_type;
|
||||
std::stringstream ss;
|
||||
ss << column_name;
|
||||
ss << " ";
|
||||
ss << operation_string(data_type, operation);
|
||||
ss << " ";
|
||||
ss << value_string(*filter, data_type);
|
||||
uiItemL(row, ss.str().c_str(), ICON_NONE);
|
||||
}
|
||||
|
||||
row = uiLayoutRow(layout, true);
|
||||
uiLayoutSetEmboss(row, UI_EMBOSS_NONE);
|
||||
const int current_index = BLI_findindex(&sspreadsheet->row_filters, filter);
|
||||
uiItemIntO(row, "", ICON_X, "SPREADSHEET_OT_remove_row_filter_rule", "index", current_index);
|
||||
|
||||
/* Some padding so the X isn't too close to the drag icon. */
|
||||
uiItemS_ex(layout, 0.25f);
|
||||
}
|
||||
|
||||
static void spreadsheet_filter_panel_draw(const bContext *C, Panel *panel)
|
||||
{
|
||||
uiLayout *layout = panel->layout;
|
||||
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
|
||||
PointerRNA *filter_ptr = UI_panel_custom_data_get(panel);
|
||||
SpreadsheetRowFilter *filter = (SpreadsheetRowFilter *)filter_ptr->data;
|
||||
const StringRef column_name = filter->column_name;
|
||||
const eSpreadsheetFilterOperation operation = (eSpreadsheetFilterOperation)filter->operation;
|
||||
|
||||
const SpreadsheetColumn *column = lookup_visible_column_for_filter(*sspreadsheet, column_name);
|
||||
if (!(sspreadsheet->filter_flag & SPREADSHEET_FILTER_ENABLE) ||
|
||||
!(filter->flag & SPREADSHEET_ROW_FILTER_ENABLED) ||
|
||||
(column == nullptr && !column_name.is_empty())) {
|
||||
uiLayoutSetActive(layout, false);
|
||||
}
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
uiLayoutSetPropDecorate(layout, false);
|
||||
|
||||
uiItemR(layout, filter_ptr, "column_name", 0, IFACE_("Column"), ICON_NONE);
|
||||
|
||||
/* Don't draw settings for filters with no corresponding visible column. */
|
||||
if (column == nullptr || column_name.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (static_cast<eSpreadsheetColumnValueType>(column->data_type)) {
|
||||
case SPREADSHEET_VALUE_TYPE_INT32:
|
||||
uiItemR(layout, filter_ptr, "operation", 0, nullptr, ICON_NONE);
|
||||
uiItemR(layout, filter_ptr, "value_int", 0, IFACE_("Value"), ICON_NONE);
|
||||
break;
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT:
|
||||
uiItemR(layout, filter_ptr, "operation", 0, nullptr, ICON_NONE);
|
||||
uiItemR(layout, filter_ptr, "value_float", 0, IFACE_("Value"), ICON_NONE);
|
||||
if (operation == SPREADSHEET_ROW_FILTER_EQUAL) {
|
||||
uiItemR(layout, filter_ptr, "threshold", 0, nullptr, ICON_NONE);
|
||||
}
|
||||
break;
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT2:
|
||||
uiItemR(layout, filter_ptr, "operation", 0, nullptr, ICON_NONE);
|
||||
uiItemR(layout, filter_ptr, "value_float2", 0, IFACE_("Value"), ICON_NONE);
|
||||
if (operation == SPREADSHEET_ROW_FILTER_EQUAL) {
|
||||
uiItemR(layout, filter_ptr, "threshold", 0, nullptr, ICON_NONE);
|
||||
}
|
||||
break;
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT3:
|
||||
uiItemR(layout, filter_ptr, "operation", 0, nullptr, ICON_NONE);
|
||||
uiItemR(layout, filter_ptr, "value_float3", 0, IFACE_("Value"), ICON_NONE);
|
||||
if (operation == SPREADSHEET_ROW_FILTER_EQUAL) {
|
||||
uiItemR(layout, filter_ptr, "threshold", 0, nullptr, ICON_NONE);
|
||||
}
|
||||
break;
|
||||
case SPREADSHEET_VALUE_TYPE_BOOL:
|
||||
uiItemR(layout, filter_ptr, "value_boolean", 0, IFACE_("Value"), ICON_NONE);
|
||||
break;
|
||||
case SPREADSHEET_VALUE_TYPE_INSTANCES:
|
||||
uiItemR(layout, filter_ptr, "value_string", 0, IFACE_("Value"), ICON_NONE);
|
||||
break;
|
||||
case SPREADSHEET_VALUE_TYPE_COLOR:
|
||||
uiItemR(layout, filter_ptr, "value_color", 0, IFACE_("Value"), ICON_NONE);
|
||||
uiItemR(layout, filter_ptr, "threshold", 0, nullptr, ICON_NONE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void spreadsheet_row_filters_layout(const bContext *C, Panel *panel)
|
||||
{
|
||||
uiLayout *layout = panel->layout;
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
|
||||
ListBase *row_filters = &sspreadsheet->row_filters;
|
||||
|
||||
if (!(sspreadsheet->filter_flag & SPREADSHEET_FILTER_ENABLE)) {
|
||||
uiLayoutSetActive(layout, false);
|
||||
}
|
||||
|
||||
uiItemO(layout, nullptr, ICON_ADD, "SPREADSHEET_OT_add_row_filter_rule");
|
||||
|
||||
const bool panels_match = UI_panel_list_matches_data(region, row_filters, filter_panel_id_fn);
|
||||
|
||||
if (!panels_match) {
|
||||
UI_panels_free_instanced(C, region);
|
||||
LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, row_filters) {
|
||||
char panel_idname[MAX_NAME];
|
||||
filter_panel_id_fn(row_filter, panel_idname);
|
||||
|
||||
PointerRNA *filter_ptr = (PointerRNA *)MEM_mallocN(sizeof(PointerRNA), "panel customdata");
|
||||
RNA_pointer_create(&screen->id, &RNA_SpreadsheetRowFilter, row_filter, filter_ptr);
|
||||
|
||||
UI_panel_add_instanced(C, region, ®ion->panels, panel_idname, filter_ptr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Assuming there's only one group of instanced panels, update the custom data pointers. */
|
||||
Panel *panel = (Panel *)region->panels.first;
|
||||
LISTBASE_FOREACH (SpreadsheetRowFilter *, row_filter, row_filters) {
|
||||
|
||||
/* Move to the next instanced panel corresponding to the next filter. */
|
||||
while ((panel->type == nullptr) || !(panel->type->flag & PANEL_TYPE_INSTANCED)) {
|
||||
panel = panel->next;
|
||||
BLI_assert(panel != nullptr); /* There shouldn't be fewer panels than filters. */
|
||||
}
|
||||
|
||||
PointerRNA *filter_ptr = (PointerRNA *)MEM_mallocN(sizeof(PointerRNA), "panel customdata");
|
||||
RNA_pointer_create(&screen->id, &RNA_SpreadsheetRowFilter, row_filter, filter_ptr);
|
||||
UI_panel_custom_data_set(panel, filter_ptr);
|
||||
|
||||
panel = panel->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void filter_reorder(bContext *C, Panel *panel, int new_index)
|
||||
{
|
||||
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
|
||||
ListBase *row_filters = &sspreadsheet->row_filters;
|
||||
PointerRNA *filter_ptr = UI_panel_custom_data_get(panel);
|
||||
SpreadsheetRowFilter *filter = (SpreadsheetRowFilter *)filter_ptr->data;
|
||||
|
||||
int current_index = BLI_findindex(row_filters, filter);
|
||||
BLI_assert(current_index >= 0);
|
||||
BLI_assert(new_index >= 0);
|
||||
|
||||
BLI_listbase_link_move(row_filters, filter, new_index - current_index);
|
||||
}
|
||||
|
||||
static short get_filter_expand_flag(const bContext *UNUSED(C), Panel *panel)
|
||||
{
|
||||
PointerRNA *filter_ptr = UI_panel_custom_data_get(panel);
|
||||
SpreadsheetRowFilter *filter = (SpreadsheetRowFilter *)filter_ptr->data;
|
||||
|
||||
return (short)filter->flag & SPREADSHEET_ROW_FILTER_UI_EXPAND;
|
||||
}
|
||||
|
||||
static void set_filter_expand_flag(const bContext *UNUSED(C), Panel *panel, short expand_flag)
|
||||
{
|
||||
PointerRNA *filter_ptr = UI_panel_custom_data_get(panel);
|
||||
SpreadsheetRowFilter *filter = (SpreadsheetRowFilter *)filter_ptr->data;
|
||||
|
||||
SET_FLAG_FROM_TEST(filter->flag,
|
||||
expand_flag & SPREADSHEET_ROW_FILTER_UI_EXPAND,
|
||||
SPREADSHEET_ROW_FILTER_UI_EXPAND);
|
||||
}
|
||||
|
||||
void register_row_filter_panels(ARegionType ®ion_type)
|
||||
{
|
||||
{
|
||||
PanelType *panel_type = (PanelType *)MEM_callocN(sizeof(PanelType), __func__);
|
||||
strcpy(panel_type->idname, "SPREADSHEET_PT_row_filters");
|
||||
strcpy(panel_type->label, N_("Filters"));
|
||||
strcpy(panel_type->category, "Filters");
|
||||
strcpy(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
|
||||
panel_type->flag = PANEL_TYPE_NO_HEADER;
|
||||
panel_type->draw = spreadsheet_row_filters_layout;
|
||||
BLI_addtail(®ion_type.paneltypes, panel_type);
|
||||
}
|
||||
|
||||
{
|
||||
PanelType *panel_type = (PanelType *)MEM_callocN(sizeof(PanelType), __func__);
|
||||
strcpy(panel_type->idname, "SPREADSHEET_PT_filter");
|
||||
strcpy(panel_type->label, "");
|
||||
strcpy(panel_type->category, "Filters");
|
||||
strcpy(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
|
||||
panel_type->flag = PANEL_TYPE_INSTANCED | PANEL_TYPE_DRAW_BOX | PANEL_TYPE_HEADER_EXPAND;
|
||||
panel_type->draw_header = spreadsheet_filter_panel_draw_header;
|
||||
panel_type->draw = spreadsheet_filter_panel_draw;
|
||||
panel_type->get_list_data_expand_flag = get_filter_expand_flag;
|
||||
panel_type->set_list_data_expand_flag = set_filter_expand_flag;
|
||||
panel_type->reorder = filter_reorder;
|
||||
BLI_addtail(®ion_type.paneltypes, panel_type);
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
struct ARegionType;
|
||||
|
||||
void register_row_filter_panels(ARegionType ®ion_type);
|
@@ -1874,6 +1874,19 @@ typedef struct SpreadsheetColumn {
|
||||
* #SpreadsheetColumnID in the future for different kinds of ids.
|
||||
*/
|
||||
SpreadsheetColumnID *id;
|
||||
|
||||
/**
|
||||
* An indicator of the type of values in the column, set at runtime.
|
||||
* #eSpreadsheetColumnValueType.
|
||||
*/
|
||||
uint8_t data_type;
|
||||
char _pad0[7];
|
||||
|
||||
/**
|
||||
* The final column name generated by the data source, also just
|
||||
* cached at runtime when the data source columns are generated.
|
||||
*/
|
||||
char *display_name;
|
||||
} SpreadsheetColumn;
|
||||
|
||||
/**
|
||||
@@ -1914,6 +1927,9 @@ typedef struct SpaceSpreadsheet {
|
||||
/* List of #SpreadsheetColumn. */
|
||||
ListBase columns;
|
||||
|
||||
/* SpreadsheetRowFilter. */
|
||||
ListBase row_filters;
|
||||
|
||||
/**
|
||||
* List of #SpreadsheetContext.
|
||||
* This is a path to the data that is displayed in the spreadsheet.
|
||||
@@ -1945,8 +1961,44 @@ typedef enum eSpaceSpreadsheet_Flag {
|
||||
|
||||
typedef enum eSpaceSpreadsheet_FilterFlag {
|
||||
SPREADSHEET_FILTER_SELECTED_ONLY = (1 << 0),
|
||||
SPREADSHEET_FILTER_ENABLE = (1 << 1),
|
||||
} eSpaceSpreadsheet_FilterFlag;
|
||||
|
||||
typedef struct SpreadsheetRowFilter {
|
||||
struct SpreadsheetRowFilter *next, *prev;
|
||||
|
||||
char column_name[64]; /* MAX_NAME. */
|
||||
|
||||
/* eSpreadsheetFilterOperation. */
|
||||
uint8_t operation;
|
||||
/* eSpaceSpreadsheet_RowFilterFlag. */
|
||||
uint8_t flag;
|
||||
|
||||
char _pad0[2];
|
||||
|
||||
int value_int;
|
||||
char *value_string;
|
||||
float value_float;
|
||||
float threshold;
|
||||
float value_float2[2];
|
||||
float value_float3[3];
|
||||
float value_color[4];
|
||||
|
||||
char _pad1[4];
|
||||
} SpreadsheetRowFilter;
|
||||
|
||||
typedef enum eSpaceSpreadsheet_RowFilterFlag {
|
||||
SPREADSHEET_ROW_FILTER_UI_EXPAND = (1 << 0),
|
||||
SPREADSHEET_ROW_FILTER_BOOL_VALUE = (1 << 1),
|
||||
SPREADSHEET_ROW_FILTER_ENABLED = (1 << 2),
|
||||
} eSpaceSpreadsheet_RowFilterFlag;
|
||||
|
||||
typedef enum eSpreadsheetFilterOperation {
|
||||
SPREADSHEET_ROW_FILTER_EQUAL = 0,
|
||||
SPREADSHEET_ROW_FILTER_GREATER = 1,
|
||||
SPREADSHEET_ROW_FILTER_LESS = 2,
|
||||
} eSpreadsheetFilterOperation;
|
||||
|
||||
typedef enum eSpaceSpreadsheet_ObjectEvalState {
|
||||
SPREADSHEET_OBJECT_EVAL_STATE_EVALUATED = 0,
|
||||
SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL = 1,
|
||||
@@ -1958,6 +2010,16 @@ typedef enum eSpaceSpreadsheet_ContextType {
|
||||
SPREADSHEET_CONTEXT_NODE = 2,
|
||||
} eSpaceSpreadsheet_ContextType;
|
||||
|
||||
typedef enum eSpreadsheetColumnValueType {
|
||||
SPREADSHEET_VALUE_TYPE_BOOL = 0,
|
||||
SPREADSHEET_VALUE_TYPE_INT32 = 1,
|
||||
SPREADSHEET_VALUE_TYPE_FLOAT = 2,
|
||||
SPREADSHEET_VALUE_TYPE_FLOAT2 = 3,
|
||||
SPREADSHEET_VALUE_TYPE_FLOAT3 = 4,
|
||||
SPREADSHEET_VALUE_TYPE_COLOR = 5,
|
||||
SPREADSHEET_VALUE_TYPE_INSTANCES = 6,
|
||||
} eSpreadsheetColumnValueType;
|
||||
|
||||
/**
|
||||
* We can't just use UI_UNIT_X, because it does not take `widget.points` into account, which
|
||||
* modifies the width of text as well.
|
||||
|
@@ -615,10 +615,12 @@ extern StructRNA RNA_Spline;
|
||||
extern StructRNA RNA_SplineIKConstraint;
|
||||
extern StructRNA RNA_SplinePoint;
|
||||
extern StructRNA RNA_SpotLight;
|
||||
extern StructRNA RNA_SpreadsheetColumnID;
|
||||
extern StructRNA RNA_SpreadsheetContext;
|
||||
extern StructRNA RNA_SpreadsheetContextObject;
|
||||
extern StructRNA RNA_SpreadsheetContextModifier;
|
||||
extern StructRNA RNA_SpreadsheetContextNode;
|
||||
extern StructRNA RNA_SpreadsheetRowFilter;
|
||||
extern StructRNA RNA_Stereo3dDisplay;
|
||||
extern StructRNA RNA_StretchToConstraint;
|
||||
extern StructRNA RNA_StringAttribute;
|
||||
|
@@ -7411,6 +7411,131 @@ static void rna_def_space_clip(BlenderRNA *brna)
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
|
||||
}
|
||||
|
||||
static void rna_def_spreadsheet_column_id(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "SpreadsheetColumnID", NULL);
|
||||
RNA_def_struct_sdna(srna, "SpreadsheetColumnID");
|
||||
RNA_def_struct_ui_text(
|
||||
srna, "Spreadsheet Column ID", "Data used to identify a spreadsheet column");
|
||||
|
||||
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Column Name", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
}
|
||||
|
||||
static void rna_def_spreadsheet_column(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static const EnumPropertyItem data_type_items[] = {
|
||||
{SPREADSHEET_VALUE_TYPE_INT32, "INT32", ICON_NONE, "Integer", ""},
|
||||
{SPREADSHEET_VALUE_TYPE_FLOAT, "FLOAT", ICON_NONE, "Float", ""},
|
||||
{SPREADSHEET_VALUE_TYPE_BOOL, "BOOLEAN", ICON_NONE, "Boolean", ""},
|
||||
{SPREADSHEET_VALUE_TYPE_INSTANCES, "INSTANCES", ICON_NONE, "Instances", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
srna = RNA_def_struct(brna, "SpreadsheetColumn", NULL);
|
||||
RNA_def_struct_sdna(srna, "SpreadsheetColumn");
|
||||
RNA_def_struct_ui_text(
|
||||
srna, "Spreadsheet Column", "Persistent data associated with a spreadsheet column");
|
||||
|
||||
prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "data_type");
|
||||
RNA_def_property_enum_items(prop, data_type_items);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Data Type", "The data type of the corresponding column visible in the spreadsheet");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
rna_def_spreadsheet_column_id(brna);
|
||||
|
||||
prop = RNA_def_property(srna, "id", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "SpreadsheetColumnID");
|
||||
RNA_def_property_ui_text(
|
||||
prop, "ID", "Data used to identify the corresponding data from the data source");
|
||||
}
|
||||
|
||||
static void rna_def_spreadsheet_row_filter(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static const EnumPropertyItem rule_operation_items[] = {
|
||||
{SPREADSHEET_ROW_FILTER_EQUAL, "EQUAL", ICON_NONE, "Equal To", ""},
|
||||
{SPREADSHEET_ROW_FILTER_GREATER, "GREATER", ICON_NONE, "Greater Than", ""},
|
||||
{SPREADSHEET_ROW_FILTER_LESS, "LESS", ICON_NONE, "Less Than", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
srna = RNA_def_struct(brna, "SpreadsheetRowFilter", NULL);
|
||||
RNA_def_struct_sdna(srna, "SpreadsheetRowFilter");
|
||||
RNA_def_struct_ui_text(srna, "Spreadsheet Row Filter", "");
|
||||
|
||||
prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SPREADSHEET_ROW_FILTER_ENABLED);
|
||||
RNA_def_property_ui_text(prop, "Enabled", "");
|
||||
RNA_def_property_ui_icon(prop, ICON_CHECKBOX_DEHLT, 1);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SPREADSHEET_ROW_FILTER_UI_EXPAND);
|
||||
RNA_def_property_ui_text(prop, "Show Expanded", "");
|
||||
RNA_def_property_ui_icon(prop, ICON_DISCLOSURE_TRI_RIGHT, 1);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "column_name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Column Name", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, rule_operation_items);
|
||||
RNA_def_property_ui_text(prop, "Operation", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "value_float", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Float Value", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "value_float2", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_array(prop, 2);
|
||||
RNA_def_property_ui_text(prop, "2D Vector Value", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "value_float3", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Vector Value", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "value_color", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_array(prop, 4);
|
||||
RNA_def_property_ui_text(prop, "Color Value", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "value_string", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Text Value", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Threshold", "How close float values need to be to be equal");
|
||||
RNA_def_property_range(prop, 0.0, FLT_MAX);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "value_int", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "value_int");
|
||||
RNA_def_property_ui_text(prop, "Integer Value", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "value_boolean", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SPREADSHEET_ROW_FILTER_BOOL_VALUE);
|
||||
RNA_def_property_ui_text(prop, "Boolean Value", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
}
|
||||
|
||||
static const EnumPropertyItem spreadsheet_context_type_items[] = {
|
||||
{SPREADSHEET_CONTEXT_OBJECT, "OBJECT", ICON_NONE, "Object", ""},
|
||||
{SPREADSHEET_CONTEXT_MODIFIER, "MODIFIER", ICON_NONE, "Modifier", ""},
|
||||
@@ -7545,13 +7670,18 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna)
|
||||
srna = RNA_def_struct(brna, "SpaceSpreadsheet", "Space");
|
||||
RNA_def_struct_ui_text(srna, "Space Spreadsheet", "Spreadsheet space data");
|
||||
|
||||
rna_def_space_generic_show_region_toggles(srna, (1 << RGN_TYPE_FOOTER));
|
||||
rna_def_space_generic_show_region_toggles(srna, (1 << RGN_TYPE_UI) | (1 << RGN_TYPE_FOOTER));
|
||||
|
||||
prop = RNA_def_property(srna, "is_pinned", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SPREADSHEET_FLAG_PINNED);
|
||||
RNA_def_property_ui_text(prop, "Is Pinned", "Context path is pinned");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_filter", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "filter_flag", SPREADSHEET_FILTER_ENABLE);
|
||||
RNA_def_property_ui_text(prop, "Use Filter", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "display_context_path_collapsed", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SPREADSHEET_FLAG_CONTEXT_PATH_COLLAPSED);
|
||||
RNA_def_property_ui_text(prop, "Display Context Path Collapsed", "");
|
||||
@@ -7566,6 +7696,7 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna)
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "filter_flag", SPREADSHEET_FILTER_SELECTED_ONLY);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Show Only Selected", "Only include rows that correspond to selected elements");
|
||||
RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 0);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "geometry_component_type", PROP_ENUM, PROP_NONE);
|
||||
@@ -7587,6 +7718,22 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Object Evaluation State", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
rna_def_spreadsheet_column(brna);
|
||||
|
||||
prop = RNA_def_property(srna, "columns", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "columns", NULL);
|
||||
RNA_def_property_struct_type(prop, "SpreadsheetColumn");
|
||||
RNA_def_property_ui_text(prop, "Columns", "Persistent data associated with spreadsheet columns");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
rna_def_spreadsheet_row_filter(brna);
|
||||
|
||||
prop = RNA_def_property(srna, "row_filters", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "row_filters", NULL);
|
||||
RNA_def_property_struct_type(prop, "SpreadsheetRowFilter");
|
||||
RNA_def_property_ui_text(prop, "Row Filters", "Filters to remove rows from the displayed data");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
func = RNA_def_function(
|
||||
srna, "set_geometry_node_context", "rna_spreadsheet_set_geometry_node_context");
|
||||
RNA_def_function_ui_description(
|
||||
|
Reference in New Issue
Block a user