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
This commit is contained in:
parent
841df831e8
commit
ae085e301c
Notes:
blender-bot
2023-02-14 02:22:07 +01:00
Referenced by issue #89498, Blender file view- can not traverse through directory structure or open files in icon (thumbnail) view Referenced by issue #89449, UI: File Browser Preview Image not responsive to click Referenced by issue #86392, Dataset region for spreadsheet editor
|
@ -1041,6 +1041,11 @@ const bTheme U_theme_default = {
|
|||
.active_object = RGBA(0xffaf29ff),
|
||||
.edited_object = RGBA(0x00806266),
|
||||
.row_alternate = RGBA(0xffffff07),
|
||||
.list = RGBA(0x424242ff),
|
||||
.list_title = RGBA(0xc3c3c3ff),
|
||||
.list_text = RGBA(0xc3c3c3ff),
|
||||
.list_text_hi = RGBA(0xffffff),
|
||||
.hilite = RGBA(0x80808080),
|
||||
},
|
||||
.tarm = {
|
||||
{
|
||||
|
|
|
@ -187,7 +187,7 @@ def _template_items_context_panel(menu, key_args_primary):
|
|||
]
|
||||
|
||||
|
||||
def _template_space_region_type_toggle(*, toolbar_key=None, sidebar_key=None):
|
||||
def _template_space_region_type_toggle(*, toolbar_key=None, sidebar_key=None, channels_key=None):
|
||||
items = []
|
||||
if toolbar_key is not None:
|
||||
items.append(
|
||||
|
@ -199,6 +199,12 @@ def _template_space_region_type_toggle(*, toolbar_key=None, sidebar_key=None):
|
|||
("wm.context_toggle", sidebar_key,
|
||||
{"properties": [("data_path", 'space_data.show_region_ui')]}),
|
||||
)
|
||||
if channels_key is not None:
|
||||
items.append(
|
||||
("wm.context_toggle", channels_key,
|
||||
{"properties": [("data_path", 'space_data.show_region_channels')]}),
|
||||
)
|
||||
|
||||
return items
|
||||
|
||||
|
||||
|
@ -3021,6 +3027,7 @@ def km_spreadsheet_generic(_params):
|
|||
items.extend([
|
||||
*_template_space_region_type_toggle(
|
||||
sidebar_key={"type": 'N', "value": 'PRESS'},
|
||||
channels_key={"type": 'T', "value": 'PRESS'},
|
||||
),
|
||||
])
|
||||
|
||||
|
|
|
@ -2143,6 +2143,21 @@ 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(
|
||||
channels_key={"type": 'T', "value": 'PRESS'},
|
||||
),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Animation
|
||||
|
|
|
@ -41,10 +41,6 @@ class SPREADSHEET_HT_header(bpy.types.Header):
|
|||
return
|
||||
|
||||
layout.prop(space, "object_eval_state", text="")
|
||||
if space.object_eval_state != 'ORIGINAL':
|
||||
layout.prop(space, "geometry_component_type", text="")
|
||||
if space.geometry_component_type != 'INSTANCES':
|
||||
layout.prop(space, "attribute_domain", text="")
|
||||
|
||||
context_path = space.context_path
|
||||
if space.object_eval_state == 'ORIGINAL':
|
||||
|
|
|
@ -38,12 +38,16 @@ struct ID;
|
|||
struct ReportList;
|
||||
|
||||
/* Attribute.domain */
|
||||
/**
|
||||
* \warning: Careful when changing existing items. Arrays may be initialized from this (e.g.
|
||||
* #DATASET_layout_hierarchy).
|
||||
*/
|
||||
typedef enum AttributeDomain {
|
||||
ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */
|
||||
ATTR_DOMAIN_POINT = 0, /* Mesh, Hair or PointCloud Point */
|
||||
ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */
|
||||
ATTR_DOMAIN_CORNER = 2, /* Mesh Corner */
|
||||
ATTR_DOMAIN_FACE = 3, /* Mesh Face */
|
||||
ATTR_DOMAIN_FACE = 2, /* Mesh Face */
|
||||
ATTR_DOMAIN_CORNER = 3, /* Mesh Corner */
|
||||
ATTR_DOMAIN_CURVE = 4, /* Hair Curve */
|
||||
|
||||
ATTR_DOMAIN_NUM
|
||||
|
|
|
@ -39,7 +39,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 4
|
||||
#define BLENDER_FILE_SUBVERSION 5
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and show a warning if the file
|
||||
|
|
|
@ -100,7 +100,7 @@ size_t BLI_str_format_int_grouped(char dst[16], int num) ATTR_NONNULL();
|
|||
size_t BLI_str_format_uint64_grouped(char dst[16], uint64_t num) ATTR_NONNULL();
|
||||
void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base_10)
|
||||
ATTR_NONNULL();
|
||||
|
||||
void BLI_str_format_attribute_domain_size(char dst[4], int number_to_format) ATTR_NONNULL();
|
||||
int BLI_strcaseeq(const char *a, const char *b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
char *BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
char *BLI_strncasestr(const char *s, const char *find, size_t len) ATTR_WARN_UNUSED_RESULT
|
||||
|
|
|
@ -1229,6 +1229,44 @@ void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base
|
|||
BLI_strncpy(dst + len, base_10 ? units_base_10[order] : units_base_2[order], dst_len - len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a attribute domain to a up to 6 places (plus '\0' terminator) string using long number names abbreviations.
|
||||
* This function is designed to produce a compact representation of large numbers.
|
||||
* 1 -> 1
|
||||
* 15 -> 15
|
||||
* 155 -> 155
|
||||
* 1555 -> 1.6K
|
||||
* 15555 -> 15.6K
|
||||
* 155555 -> 156K
|
||||
* 1555555 -> 1.6M
|
||||
* 15555555 -> 15.6M
|
||||
* 155555555 -> 156M
|
||||
* 1000000000 -> 1B
|
||||
* ...
|
||||
* Dimension of 7 is the maximum length of the resulting string
|
||||
* A combination with 7 places would be -15.5K\0
|
||||
*/
|
||||
void BLI_str_format_attribute_domain_size(char dst[7], int number_to_format)
|
||||
{
|
||||
float number_to_format_converted = number_to_format;
|
||||
int order = 0;
|
||||
const float base = 1000;
|
||||
const char *units[] = {"", "K", "M", "B"};
|
||||
const int tot_units = ARRAY_SIZE(units);
|
||||
|
||||
while ((fabsf(number_to_format_converted) >= base) && ((order + 1) < tot_units)) {
|
||||
number_to_format_converted /= base;
|
||||
order++;
|
||||
}
|
||||
|
||||
const size_t dst_len = 7;
|
||||
int decimals = 0;
|
||||
if ((order > 0) && fabsf(number_to_format_converted) < 100.0f) {
|
||||
decimals = 1;
|
||||
}
|
||||
BLI_snprintf(dst, dst_len, "%.*f%s", decimals, number_to_format_converted, units[order]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the ranges needed to split \a str into its individual words.
|
||||
*
|
||||
|
|
|
@ -420,6 +420,101 @@ TEST(string, StrFormatByteUnits)
|
|||
EXPECT_STREQ("-8191.8472 PiB", size_str);
|
||||
}
|
||||
|
||||
/* BLI_str_format_attribute_domain_size */
|
||||
TEST(string, StrFormatAttributeDomainSize)
|
||||
{
|
||||
char size_str[7];
|
||||
int size;
|
||||
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 0);
|
||||
EXPECT_STREQ("0", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 1);
|
||||
EXPECT_STREQ("1", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 10);
|
||||
EXPECT_STREQ("10", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 15);
|
||||
EXPECT_STREQ("15", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 100);
|
||||
EXPECT_STREQ("100", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 155);
|
||||
EXPECT_STREQ("155", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 1000);
|
||||
EXPECT_STREQ("1.0K", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 1555);
|
||||
EXPECT_STREQ("1.6K", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 10000);
|
||||
EXPECT_STREQ("10.0K", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 15555);
|
||||
EXPECT_STREQ("15.6K", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 100000);
|
||||
EXPECT_STREQ("100K", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 100000);
|
||||
EXPECT_STREQ("100K", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 155555);
|
||||
EXPECT_STREQ("156K", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 1000000);
|
||||
EXPECT_STREQ("1.0M", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 1555555);
|
||||
EXPECT_STREQ("1.6M", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 10000000);
|
||||
EXPECT_STREQ("10.0M", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 15555555);
|
||||
EXPECT_STREQ("15.6M", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 100000000);
|
||||
EXPECT_STREQ("100M", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 155555555);
|
||||
EXPECT_STREQ("156M", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = 1000000000);
|
||||
EXPECT_STREQ("1.0B", size_str);
|
||||
|
||||
/* Largest possible value. */
|
||||
BLI_str_format_attribute_domain_size(size_str, size = INT32_MAX);
|
||||
EXPECT_STREQ("2.1B", size_str);
|
||||
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -0);
|
||||
EXPECT_STREQ("0", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -1);
|
||||
EXPECT_STREQ("-1", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -10);
|
||||
EXPECT_STREQ("-10", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -15);
|
||||
EXPECT_STREQ("-15", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -100);
|
||||
EXPECT_STREQ("-100", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -155);
|
||||
EXPECT_STREQ("-155", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -1000);
|
||||
EXPECT_STREQ("-1.0K", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -1555);
|
||||
EXPECT_STREQ("-1.6K", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -10000);
|
||||
EXPECT_STREQ("-10.0K", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -15555);
|
||||
EXPECT_STREQ("-15.6K", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -100000);
|
||||
EXPECT_STREQ("-100K", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -155555);
|
||||
EXPECT_STREQ("-156K", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -1000000);
|
||||
EXPECT_STREQ("-1.0M", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -1555555);
|
||||
EXPECT_STREQ("-1.6M", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -10000000);
|
||||
EXPECT_STREQ("-10.0M", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -15555555);
|
||||
EXPECT_STREQ("-15.6M", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -100000000);
|
||||
EXPECT_STREQ("-100M", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -155555555);
|
||||
EXPECT_STREQ("-156M", size_str);
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -1000000000);
|
||||
EXPECT_STREQ("-1.0B", size_str);
|
||||
|
||||
/* Smallest possible value. */
|
||||
BLI_str_format_attribute_domain_size(size_str, size = -INT32_MAX);
|
||||
EXPECT_STREQ("-2.1B", size_str);
|
||||
}
|
||||
|
||||
struct WordInfo {
|
||||
WordInfo() = default;
|
||||
WordInfo(int start, int end) : start(start), end(end)
|
||||
|
|
|
@ -40,7 +40,9 @@
|
|||
#include "BKE_node.h"
|
||||
|
||||
#include "BLO_readfile.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
#include "readfile.h"
|
||||
#include "versioning_common.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
|
@ -122,6 +124,7 @@ void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports))
|
|||
sort_linked_ids(bmain);
|
||||
assert_sorted_ids(bmain);
|
||||
}
|
||||
|
||||
if (MAIN_VERSION_ATLEAST(bmain, 300, 3)) {
|
||||
assert_sorted_ids(bmain);
|
||||
}
|
||||
|
@ -392,6 +395,26 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 300, 5)) {
|
||||
/* Add a dataset 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 *spreadsheet_dataset_region = do_versions_add_region_if_not_found(
|
||||
regionbase, RGN_TYPE_CHANNELS, "spreadsheet dataset region", RGN_TYPE_FOOTER);
|
||||
|
||||
if (spreadsheet_dataset_region) {
|
||||
spreadsheet_dataset_region->alignment = RGN_ALIGN_LEFT;
|
||||
spreadsheet_dataset_region->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
|
|
|
@ -277,6 +277,15 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
|
|||
btheme->space_spreadsheet = btheme->space_outliner;
|
||||
}
|
||||
|
||||
if (!USER_VERSION_ATLEAST(300, 5)) {
|
||||
FROM_DEFAULT_V4_UCHAR(space_spreadsheet.active);
|
||||
FROM_DEFAULT_V4_UCHAR(space_spreadsheet.list);
|
||||
FROM_DEFAULT_V4_UCHAR(space_spreadsheet.list_text);
|
||||
FROM_DEFAULT_V4_UCHAR(space_spreadsheet.list_text_hi);
|
||||
FROM_DEFAULT_V4_UCHAR(space_spreadsheet.hilite);
|
||||
FROM_DEFAULT_V4_UCHAR(space_spreadsheet.selected_highlight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
|
|
|
@ -30,9 +30,9 @@ struct SpreadsheetContext *ED_spreadsheet_context_new(int type);
|
|||
void ED_spreadsheet_context_free(struct SpreadsheetContext *context);
|
||||
void ED_spreadsheet_context_path_clear(struct SpaceSpreadsheet *sspreadsheet);
|
||||
void ED_spreadsheet_context_path_update_tag(struct SpaceSpreadsheet *sspreadsheet);
|
||||
uint64_t ED_spreadsheet_context_path_hash(struct SpaceSpreadsheet *sspreadsheet);
|
||||
uint64_t ED_spreadsheet_context_path_hash(const struct SpaceSpreadsheet *sspreadsheet);
|
||||
|
||||
struct ID *ED_spreadsheet_get_current_id(struct SpaceSpreadsheet *sspreadsheet);
|
||||
struct ID *ED_spreadsheet_get_current_id(const struct SpaceSpreadsheet *sspreadsheet);
|
||||
|
||||
void ED_spreadsheet_set_geometry_node_context(struct SpaceSpreadsheet *sspreadsheet,
|
||||
struct SpaceNode *snode,
|
||||
|
|
|
@ -386,6 +386,7 @@ typedef enum {
|
|||
/** Resize handle (resize uilist). */
|
||||
UI_BTYPE_GRIP = 57 << 9,
|
||||
UI_BTYPE_DECORATOR = 58 << 9,
|
||||
UI_BTYPE_DATASETROW = 59 << 9,
|
||||
} eButType;
|
||||
|
||||
#define BUTTYPE (63 << 9)
|
||||
|
@ -516,7 +517,7 @@ typedef struct ARegion *(*uiButSearchTooltipFn)(struct bContext *C,
|
|||
|
||||
/* Must return allocated string. */
|
||||
typedef char *(*uiButToolTipFunc)(struct bContext *C, void *argN, const char *tip);
|
||||
typedef int (*uiButPushedStateFunc)(struct bContext *C, void *arg);
|
||||
typedef int (*uiButPushedStateFunc)(struct uiBut *but, const void *arg);
|
||||
|
||||
typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event);
|
||||
|
||||
|
@ -1612,6 +1613,13 @@ int UI_searchbox_size_x(void);
|
|||
/* check if a string is in an existing search box */
|
||||
int UI_search_items_find_index(uiSearchItems *items, const char *name);
|
||||
|
||||
void UI_but_hint_drawstr_set(uiBut *but, const char *string);
|
||||
void UI_but_datasetrow_indentation_set(uiBut *but, int indentation);
|
||||
void UI_but_datasetrow_component_set(uiBut *but, uint8_t geometry_component_type);
|
||||
void UI_but_datasetrow_domain_set(uiBut *but, uint8_t attribute_domain);
|
||||
uint8_t UI_but_datasetrow_component_get(uiBut *but);
|
||||
uint8_t UI_but_datasetrow_domain_get(uiBut *but);
|
||||
|
||||
void UI_but_node_link_set(uiBut *but, struct bNodeSocket *socket, const float draw_color[4]);
|
||||
|
||||
void UI_but_number_step_size_set(uiBut *but, float step_size);
|
||||
|
@ -1650,7 +1658,7 @@ void UI_but_focus_on_enter_event(struct wmWindow *win, uiBut *but);
|
|||
|
||||
void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN);
|
||||
|
||||
void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, void *arg);
|
||||
void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, const void *arg);
|
||||
|
||||
struct PointerRNA *UI_but_extra_operator_icon_add(uiBut *but,
|
||||
const char *opname,
|
||||
|
|
|
@ -2105,8 +2105,10 @@ void UI_region_message_subscribe(ARegion *region, struct wmMsgBus *mbus)
|
|||
int ui_but_is_pushed_ex(uiBut *but, double *value)
|
||||
{
|
||||
int is_push = 0;
|
||||
|
||||
if (but->bit) {
|
||||
if (but->pushed_state_func) {
|
||||
return but->pushed_state_func(but, but->pushed_state_arg);
|
||||
}
|
||||
else if (but->bit) {
|
||||
const bool state = !ELEM(
|
||||
but->type, UI_BTYPE_TOGGLE_N, UI_BTYPE_ICON_TOGGLE_N, UI_BTYPE_CHECKBOX_N);
|
||||
int lvalue;
|
||||
|
@ -2253,7 +2255,6 @@ void ui_but_v3_get(uiBut *but, float vec[3])
|
|||
}
|
||||
else if (but->pointype == UI_BUT_POIN_CHAR) {
|
||||
const char *cp = (char *)but->poin;
|
||||
|
||||
vec[0] = ((float)cp[0]) / 255.0f;
|
||||
vec[1] = ((float)cp[1]) / 255.0f;
|
||||
vec[2] = ((float)cp[2]) / 255.0f;
|
||||
|
@ -3903,6 +3904,10 @@ static void ui_but_alloc_info(const eButType type,
|
|||
alloc_size = sizeof(uiButCurveProfile);
|
||||
alloc_str = "uiButCurveProfile";
|
||||
break;
|
||||
case UI_BTYPE_DATASETROW:
|
||||
alloc_size = sizeof(uiButDatasetRow);
|
||||
alloc_str = "uiButDatasetRow";
|
||||
break;
|
||||
default:
|
||||
alloc_size = sizeof(uiBut);
|
||||
alloc_str = "uiBut";
|
||||
|
@ -4100,6 +4105,7 @@ static uiBut *ui_def_but(uiBlock *block,
|
|||
UI_BTYPE_BUT_MENU,
|
||||
UI_BTYPE_SEARCH_MENU,
|
||||
UI_BTYPE_PROGRESS_BAR,
|
||||
UI_BTYPE_DATASETROW,
|
||||
UI_BTYPE_POPOVER)) {
|
||||
but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
|
||||
}
|
||||
|
@ -6336,10 +6342,11 @@ void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *argN)
|
|||
but->tip_argN = argN;
|
||||
}
|
||||
|
||||
void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, void *arg)
|
||||
void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, const void *arg)
|
||||
{
|
||||
but->pushed_state_func = func;
|
||||
but->pushed_state_arg = arg;
|
||||
ui_but_update(but);
|
||||
}
|
||||
|
||||
uiBut *uiDefBlockBut(uiBlock *block,
|
||||
|
@ -6824,6 +6831,56 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block,
|
|||
return but;
|
||||
}
|
||||
|
||||
void UI_but_datasetrow_indentation_set(uiBut *but, int indentation)
|
||||
{
|
||||
uiButDatasetRow *but_dataset = (uiButDatasetRow *)but;
|
||||
BLI_assert(but->type == UI_BTYPE_DATASETROW);
|
||||
|
||||
but_dataset->indentation = indentation;
|
||||
BLI_assert(indentation >= 0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a hint to the button which draws right aligned, grayed out and never clipped.
|
||||
*/
|
||||
void UI_but_hint_drawstr_set(uiBut *but, const char *string)
|
||||
{
|
||||
ui_but_add_shortcut(but, string, false);
|
||||
}
|
||||
|
||||
void UI_but_datasetrow_component_set(uiBut *but, uint8_t geometry_component_type)
|
||||
{
|
||||
uiButDatasetRow *but_dataset_row = (uiButDatasetRow *)but;
|
||||
BLI_assert(but->type == UI_BTYPE_DATASETROW);
|
||||
|
||||
but_dataset_row->geometry_component_type = geometry_component_type;
|
||||
}
|
||||
|
||||
void UI_but_datasetrow_domain_set(uiBut *but, uint8_t attribute_domain)
|
||||
{
|
||||
uiButDatasetRow *but_dataset_row = (uiButDatasetRow *)but;
|
||||
BLI_assert(but->type == UI_BTYPE_DATASETROW);
|
||||
|
||||
but_dataset_row->attribute_domain = attribute_domain;
|
||||
}
|
||||
|
||||
uint8_t UI_but_datasetrow_component_get(uiBut *but)
|
||||
{
|
||||
uiButDatasetRow *but_dataset_row = (uiButDatasetRow *)but;
|
||||
BLI_assert(but->type == UI_BTYPE_DATASETROW);
|
||||
|
||||
return but_dataset_row->geometry_component_type;
|
||||
}
|
||||
|
||||
uint8_t UI_but_datasetrow_domain_get(uiBut *but)
|
||||
{
|
||||
uiButDatasetRow *but_dataset_row = (uiButDatasetRow *)but;
|
||||
BLI_assert(but->type == UI_BTYPE_DATASETROW);
|
||||
|
||||
return but_dataset_row->attribute_domain;
|
||||
}
|
||||
|
||||
void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4])
|
||||
{
|
||||
but->flag |= UI_BUT_NODE_LINK;
|
||||
|
|
|
@ -1461,12 +1461,9 @@ static bool ui_drag_toggle_but_is_supported(const uiBut *but)
|
|||
|
||||
/* Button pushed state to compare if other buttons match. Can be more
|
||||
* then just true or false for toggle buttons with more than 2 states. */
|
||||
static int ui_drag_toggle_but_pushed_state(bContext *C, uiBut *but)
|
||||
static int ui_drag_toggle_but_pushed_state(uiBut *but)
|
||||
{
|
||||
if (but->rnapoin.data == NULL && but->poin == NULL && but->icon) {
|
||||
if (but->pushed_state_func) {
|
||||
return but->pushed_state_func(C, but->pushed_state_arg);
|
||||
}
|
||||
/* Assume icon identifies a unique state, for buttons that
|
||||
* work through functions callbacks and don't have an boolean
|
||||
* value that indicates the state. */
|
||||
|
@ -1513,7 +1510,7 @@ static bool ui_drag_toggle_set_xy_xy(
|
|||
/* execute the button */
|
||||
if (ui_drag_toggle_but_is_supported(but)) {
|
||||
/* is it pressed? */
|
||||
const int pushed_state_but = ui_drag_toggle_but_pushed_state(C, but);
|
||||
const int pushed_state_but = ui_drag_toggle_but_pushed_state(but);
|
||||
if (pushed_state_but != pushed_state) {
|
||||
UI_but_execute(C, region, but);
|
||||
if (do_check) {
|
||||
|
@ -1943,7 +1940,7 @@ static bool ui_but_drag_init(bContext *C,
|
|||
* typically 'button_activate_exit()' handles this */
|
||||
ui_apply_but_autokey(C, but);
|
||||
|
||||
drag_info->pushed_state = ui_drag_toggle_but_pushed_state(C, but);
|
||||
drag_info->pushed_state = ui_drag_toggle_but_pushed_state(but);
|
||||
drag_info->but_cent_start[0] = BLI_rctf_cent_x(&but->rect);
|
||||
drag_info->but_cent_start[1] = BLI_rctf_cent_y(&but->rect);
|
||||
copy_v2_v2_int(drag_info->xy_init, &event->x);
|
||||
|
@ -2187,6 +2184,9 @@ static void ui_apply_but(
|
|||
case UI_BTYPE_LISTROW:
|
||||
ui_apply_but_ROW(C, block, but, data);
|
||||
break;
|
||||
case UI_BTYPE_DATASETROW:
|
||||
ui_apply_but_ROW(C, block, but, data);
|
||||
break;
|
||||
case UI_BTYPE_TAB:
|
||||
ui_apply_but_TAB(C, but, data);
|
||||
break;
|
||||
|
@ -7851,6 +7851,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
|
|||
case UI_BTYPE_LABEL:
|
||||
case UI_BTYPE_IMAGE:
|
||||
case UI_BTYPE_PROGRESS_BAR:
|
||||
case UI_BTYPE_DATASETROW:
|
||||
retval = ui_do_but_TOG(C, but, data, event);
|
||||
break;
|
||||
case UI_BTYPE_NODE_SOCKET:
|
||||
retval = ui_do_but_EXIT(C, but, data, event);
|
||||
break;
|
||||
|
|
|
@ -279,7 +279,7 @@ struct uiBut {
|
|||
float *editvec;
|
||||
|
||||
uiButPushedStateFunc pushed_state_func;
|
||||
void *pushed_state_arg;
|
||||
const void *pushed_state_arg;
|
||||
|
||||
/* pointer back */
|
||||
uiBlock *block;
|
||||
|
@ -350,6 +350,15 @@ typedef struct uiButProgressbar {
|
|||
float progress;
|
||||
} uiButProgressbar;
|
||||
|
||||
/** Derived struct for #UI_BTYPE_DATASETROW. */
|
||||
typedef struct uiButDatasetRow {
|
||||
uiBut but;
|
||||
|
||||
uint8_t geometry_component_type;
|
||||
uint8_t attribute_domain;
|
||||
int indentation;
|
||||
} uiButDatasetRow;
|
||||
|
||||
/** Derived struct for #UI_BTYPE_HSVCUBE. */
|
||||
typedef struct uiButHSVCube {
|
||||
uiBut but;
|
||||
|
|
|
@ -67,7 +67,8 @@ bool ui_but_is_toggle(const uiBut *but)
|
|||
UI_BTYPE_TOGGLE_N,
|
||||
UI_BTYPE_CHECKBOX,
|
||||
UI_BTYPE_CHECKBOX_N,
|
||||
UI_BTYPE_ROW);
|
||||
UI_BTYPE_ROW,
|
||||
UI_BTYPE_DATASETROW);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -113,6 +113,7 @@ typedef enum {
|
|||
UI_WTYPE_LISTITEM,
|
||||
UI_WTYPE_PROGRESSBAR,
|
||||
UI_WTYPE_NODESOCKET,
|
||||
UI_WTYPE_DATASETROW,
|
||||
} uiWidgetTypeEnum;
|
||||
|
||||
/* Button state argument shares bits with 'uiBut.flag'.
|
||||
|
@ -3697,6 +3698,28 @@ static void widget_progressbar(
|
|||
rect->xmax += (BLI_rcti_size_x(&rect_prog) / 2);
|
||||
}
|
||||
|
||||
static void widget_datasetrow(
|
||||
uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign))
|
||||
{
|
||||
uiButDatasetRow *but_componentrow = (uiButDatasetRow *)but;
|
||||
uiWidgetBase wtb;
|
||||
widget_init(&wtb);
|
||||
|
||||
/* no outline */
|
||||
wtb.draw_outline = false;
|
||||
const float rad = wcol->roundness * U.widget_unit;
|
||||
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
|
||||
|
||||
if ((state & UI_ACTIVE) || (state & UI_SELECT)) {
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
}
|
||||
|
||||
BLI_rcti_resize(rect,
|
||||
BLI_rcti_size_x(rect) - UI_UNIT_X * but_componentrow->indentation,
|
||||
BLI_rcti_size_y(rect));
|
||||
BLI_rcti_translate(rect, 0.5f * UI_UNIT_X * but_componentrow->indentation, 0);
|
||||
}
|
||||
|
||||
static void widget_nodesocket(
|
||||
uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
|
||||
{
|
||||
|
@ -4469,6 +4492,10 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
|
|||
wt.custom = widget_progressbar;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_DATASETROW:
|
||||
wt.custom = widget_datasetrow;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_NODESOCKET:
|
||||
wt.custom = widget_nodesocket;
|
||||
break;
|
||||
|
@ -4792,6 +4819,11 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu
|
|||
fstyle = &style->widgetlabel;
|
||||
break;
|
||||
|
||||
case UI_BTYPE_DATASETROW:
|
||||
wt = widget_type(UI_WTYPE_DATASETROW);
|
||||
fstyle = &style->widgetlabel;
|
||||
break;
|
||||
|
||||
case UI_BTYPE_SCROLL:
|
||||
wt = widget_type(UI_WTYPE_SCROLL);
|
||||
break;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
@ -79,6 +80,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;
|
||||
}
|
||||
|
||||
{
|
||||
/* 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");
|
||||
|
@ -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)
|
|||
}
|
||||
}
|
||||
|
||||
Object *spreadsheet_get_object_eval(const SpaceSpreadsheet *sspreadsheet,
|
||||
const Depsgraph *depsgraph)
|
||||
{
|
||||
ID *used_id = ED_spreadsheet_get_current_id(sspreadsheet);
|
||||
if (used_id == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
const ID_Type id_type = GS(used_id->name);
|
||||
if (id_type != ID_OB) {
|
||||
return nullptr;
|
||||
}
|
||||
Object *object_orig = (Object *)used_id;
|
||||
if (!ELEM(object_orig->type, OB_MESH, OB_POINTCLOUD, OB_VOLUME)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, object_orig);
|
||||
if (object_eval == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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);
|
||||
ID *used_id = ED_spreadsheet_get_current_id(sspreadsheet);
|
||||
if (used_id == nullptr) {
|
||||
return {};
|
||||
}
|
||||
const ID_Type id_type = GS(used_id->name);
|
||||
if (id_type != ID_OB) {
|
||||
return {};
|
||||
}
|
||||
Object *object_orig = (Object *)used_id;
|
||||
if (!ELEM(object_orig->type, OB_MESH, OB_POINTCLOUD, OB_VOLUME)) {
|
||||
return {};
|
||||
}
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, object_orig);
|
||||
if (object_eval == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return data_source_from_geometry(C, object_eval);
|
||||
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(®ion->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(®ion->handlers, keymap);
|
||||
}
|
||||
|
||||
static void spreadsheet_dataset_region_draw(const bContext *C, ARegion *region)
|
||||
{
|
||||
spreadsheet_update_context_path(C);
|
||||
|
||||
View2D *v2d = ®ion->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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {};
|
||||
|
|
|
@ -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(®ion->v2d, region->winx, abs(drawer.ymin_offset));
|
||||
UI_block_draw(C, block);
|
||||
}
|
||||
|
||||
} // namespace blender::ed::spreadsheet
|
|
@ -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 █
|
||||
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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -776,6 +776,20 @@ static void rna_Space_show_region_toolbar_update(bContext *C, PointerRNA *ptr)
|
|||
rna_Space_bool_from_region_flag_update_by_type(C, ptr, RGN_TYPE_TOOLS, RGN_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
/* Channels Region. */
|
||||
static bool rna_Space_show_region_channels_get(PointerRNA *ptr)
|
||||
{
|
||||
return !rna_Space_bool_from_region_flag_get_by_type(ptr, RGN_TYPE_CHANNELS, RGN_FLAG_HIDDEN);
|
||||
}
|
||||
static void rna_Space_show_region_channels_set(PointerRNA *ptr, bool value)
|
||||
{
|
||||
rna_Space_bool_from_region_flag_set_by_type(ptr, RGN_TYPE_CHANNELS, RGN_FLAG_HIDDEN, !value);
|
||||
}
|
||||
static void rna_Space_show_region_channels_update(bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
rna_Space_bool_from_region_flag_update_by_type(C, ptr, RGN_TYPE_CHANNELS, RGN_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
/* UI Region */
|
||||
static bool rna_Space_show_region_ui_get(PointerRNA *ptr)
|
||||
{
|
||||
|
@ -3214,6 +3228,10 @@ static void rna_def_space_generic_show_region_toggles(StructRNA *srna, int regio
|
|||
region_type_mask &= ~(1 << RGN_TYPE_TOOLS);
|
||||
DEF_SHOW_REGION_PROPERTY(show_region_toolbar, "Toolbar", "");
|
||||
}
|
||||
if (region_type_mask & (1 << RGN_TYPE_CHANNELS)) {
|
||||
region_type_mask &= ~(1 << RGN_TYPE_CHANNELS);
|
||||
DEF_SHOW_REGION_PROPERTY(show_region_channels, "Channels", "");
|
||||
}
|
||||
if (region_type_mask & (1 << RGN_TYPE_UI)) {
|
||||
region_type_mask &= ~(1 << RGN_TYPE_UI);
|
||||
DEF_SHOW_REGION_PROPERTY(show_region_ui, "Sidebar", "");
|
||||
|
@ -7560,6 +7578,9 @@ static void rna_def_space_spreadsheet_context(BlenderRNA *brna)
|
|||
RNA_def_property_enum_items(prop, spreadsheet_context_type_items);
|
||||
RNA_def_property_ui_text(prop, "Type", "Type of the context");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
rna_def_space_generic_show_region_toggles(srna,
|
||||
(1 << RGN_TYPE_CHANNELS) | (1 << RGN_TYPE_FOOTER));
|
||||
}
|
||||
|
||||
static void rna_def_space_spreadsheet_context_object(BlenderRNA *brna)
|
||||
|
@ -7674,7 +7695,7 @@ 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_UI) | (1 << RGN_TYPE_FOOTER));
|
||||
rna_def_space_generic_show_region_toggles(srna, (1 << RGN_TYPE_UI) | (1 << RGN_TYPE_CHANNELS) | (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);
|
||||
|
|
|
@ -3864,6 +3864,7 @@ static void rna_def_userdef_theme_space_spreadsheet(BlenderRNA *brna)
|
|||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
|
||||
rna_def_userdef_theme_spaces_main(srna);
|
||||
rna_def_userdef_theme_spaces_list_main(srna);
|
||||
}
|
||||
|
||||
static void rna_def_userdef_themes(BlenderRNA *brna)
|
||||
|
|
Loading…
Reference in New Issue