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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2020-10-13 21:10:41 +0300
committerHans Goudey <h.goudey@me.com>2020-10-13 21:10:41 +0300
commit7c633686e99512d33391f30e4602213ed3890802 (patch)
tree5c0b651851d9de7896ea9687d83ed62059f84492 /source/blender
parent96dd299055a1ce35819480f3c4b938f8e6f91537 (diff)
Property Search: Find results in all tabs
This patch enables property search for all tabs in the property editor. To make interaction faster, if the editor's current tab doesn't have a result, the current tab changes to the next tab that has a match. This patch implements basic code that only searches panels. While we could run the existing "single tab" property search for every tab, that would also do everything else related to the layout pass, which would be less efficient, and maybe more complicated to maintain. The search match status for every current tab of the property editor is stored in a runtime bitfield and them displayed later by dimming icons in the tab selector panel to the left. Using `BLI_bitmap` properly in the runtime struct required moving it to `buttons_intern.h` and adding a small API to access the search filter instead. To make sure the editor isn't influenced by anything that happens while building the layout for other tabs, most of the context is duplicated and the new search is run in the duplicated editor. Note that the tool settings tab works slightly different than the other tabs, so I've disabled searching it for this commit. That would be a relatively simple improvement, but would just require a bit of refactoring of existing code. Differential Revision: https://developer.blender.org/D8859
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/editors/include/ED_buttons.h5
-rw-r--r--source/blender/editors/include/ED_screen.h5
-rw-r--r--source/blender/editors/include/UI_interface.h1
-rw-r--r--source/blender/editors/interface/interface_layout.c13
-rw-r--r--source/blender/editors/screen/area.c146
-rw-r--r--source/blender/editors/space_buttons/buttons_intern.h11
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c174
-rw-r--r--source/blender/makesdna/DNA_space_types.h12
-rw-r--r--source/blender/makesrna/intern/rna_space.c64
9 files changed, 418 insertions, 13 deletions
diff --git a/source/blender/editors/include/ED_buttons.h b/source/blender/editors/include/ED_buttons.h
index a4cd2525af3..5d153757900 100644
--- a/source/blender/editors/include/ED_buttons.h
+++ b/source/blender/editors/include/ED_buttons.h
@@ -29,6 +29,11 @@ extern "C" {
struct SpaceProperties;
int ED_buttons_tabs_list(struct SpaceProperties *sbuts, short *context_tabs_array);
+bool ED_buttons_tab_has_search_result(struct SpaceProperties *sbuts, const int index);
+
+void ED_buttons_search_string_set(struct SpaceProperties *sbuts, const char *value);
+int ED_buttons_search_string_length(struct SpaceProperties *sbuts);
+const char *ED_buttons_search_string_get(struct SpaceProperties *sbuts);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 53554e3f34c..b8500ba0c37 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -92,6 +92,11 @@ void ED_region_panels_layout_ex(const struct bContext *C,
struct ListBase *paneltypes,
const char *contexts[],
const char *category_override);
+bool ED_region_property_search(const struct bContext *C,
+ struct ARegion *region,
+ struct ListBase *paneltypes,
+ const char *contexts[],
+ const char *category_override);
void ED_region_panels_layout(const struct bContext *C, struct ARegion *region);
void ED_region_panels_draw(const struct bContext *C, struct ARegion *region);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 94095d04271..2c8518de700 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1874,6 +1874,7 @@ uiLayout *UI_block_layout(uiBlock *block,
const struct uiStyle *style);
void UI_block_layout_set_current(uiBlock *block, uiLayout *layout);
void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y);
+void UI_block_layout_free(uiBlock *block);
bool UI_block_apply_search_filter(uiBlock *block, const char *search_filter);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 98b1c020d95..3e276a69277 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -5600,6 +5600,19 @@ void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv)
layout->root->argv = argv;
}
+/**
+ * Used for property search when the layout process needs to be cancelled in order to avoid
+ * computing the locations for buttons, but the layout items created while adding the buttons
+ * must still be freed.
+ */
+void UI_block_layout_free(uiBlock *block)
+{
+ LISTBASE_FOREACH_MUTABLE (uiLayoutRoot *, root, &block->layouts) {
+ ui_layout_free(root->layout);
+ MEM_freeN(root);
+ }
+}
+
void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
{
BLI_assert(block->active);
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 6fa9d203bba..fd94eea337f 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -48,6 +48,7 @@
#include "WM_toolsystem.h"
#include "WM_types.h"
+#include "ED_buttons.h"
#include "ED_screen.h"
#include "ED_screen_types.h"
#include "ED_space_api.h"
@@ -765,7 +766,7 @@ const char *ED_area_region_search_filter_get(const ScrArea *area, const ARegion
if (area->spacetype == SPACE_PROPERTIES) {
SpaceProperties *sbuts = area->spacedata.first;
if (region->regiontype == RGN_TYPE_WINDOW) {
- return sbuts->runtime->search_string;
+ return ED_buttons_search_string_get(sbuts);
}
}
@@ -3074,6 +3075,149 @@ void ED_region_panels_init(wmWindowManager *wm, ARegion *region)
WM_event_add_keymap_handler(&region->handlers, keymap);
}
+/**
+ * Check whether any of the buttons generated by the \a panel_type's
+ * layout callbacks match the \a search_filter.
+ *
+ * \param panel: If non-NULL, use this instead of adding a new panel for the \a panel_type.
+ */
+static bool panel_property_search(const bContext *C,
+ ARegion *region,
+ const uiStyle *style,
+ Panel *panel,
+ PanelType *panel_type,
+ const char *search_filter)
+{
+ uiBlock *block = UI_block_begin(C, region, panel_type->idname, UI_EMBOSS);
+ UI_block_set_search_only(block, true);
+
+ if (panel == NULL) {
+ bool open; /* Dummy variable. */
+ panel = UI_panel_begin(region, &region->panels, block, panel_type, panel, &open);
+ }
+
+ /* Build the layouts. Because they are only used for search,
+ * they don't need any of the proper style or layout information. */
+ if (panel->type->draw_header_preset != NULL) {
+ panel->layout = UI_block_layout(
+ block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, 0, 0, 0, 0, 0, style);
+ panel_type->draw_header_preset(C, panel);
+ }
+ if (panel->type->draw_header != NULL) {
+ panel->layout = UI_block_layout(
+ block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, 0, 0, 0, 0, 0, style);
+ panel_type->draw_header(C, panel);
+ }
+ if (LIKELY(panel->type->draw != NULL)) {
+ panel->layout = UI_block_layout(
+ block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 0, 0, 0, style);
+ panel_type->draw(C, panel);
+ }
+
+ UI_block_layout_free(block);
+
+ /* We could check after each layout to increase the likelyhood of returning early,
+ * but that probably wouldn't make much of a difference anyway. */
+ if (UI_block_apply_search_filter(block, search_filter)) {
+ return true;
+ }
+
+ LISTBASE_FOREACH (LinkData *, link, &panel_type->children) {
+ PanelType *panel_type_child = link->data;
+ if (!panel_type_child->poll || panel_type_child->poll(C, panel_type_child)) {
+ /* Search for the existing child panel here because it might be an instanced
+ * child panel with a custom data field that will be needed to build the layout. */
+ Panel *child_panel = UI_panel_find_by_type(&panel->children, panel_type_child);
+ if (panel_property_search(C, region, style, child_panel, panel_type_child, search_filter)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Build the same panel list as #ED_region_panels_layout_ex and checks whether any
+ * of the panels contain a search result based on the area / region's search filter.
+ */
+bool ED_region_property_search(const bContext *C,
+ ARegion *region,
+ ListBase *paneltypes,
+ const char *contexts[],
+ const char *category_override)
+{
+ ScrArea *area = CTX_wm_area(C);
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ const uiStyle *style = UI_style_get_dpi();
+ const char *search_filter = ED_area_region_search_filter_get(area, region);
+
+ LinkNode *panel_types_stack = NULL;
+ LISTBASE_FOREACH_BACKWARD (PanelType *, pt, paneltypes) {
+ if (panel_add_check(C, workspace, contexts, category_override, pt)) {
+ BLI_linklist_prepend_alloca(&panel_types_stack, pt);
+ }
+ }
+
+ const char *category = NULL;
+ bool use_category_tabs = (category_override == NULL) && region_uses_category_tabs(area, region);
+ if (use_category_tabs) {
+ category = region_panels_collect_categories(region, panel_types_stack, &use_category_tabs);
+ }
+
+ /* Run property search for each panel, stopping if a result is found. */
+ bool has_result = true;
+ bool has_instanced_panel = false;
+ for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) {
+ PanelType *panel_type = pt_link->link;
+ /* Note that these checks are duplicated from #ED_region_panels_layout_ex. */
+ if (panel_type->flag & PNL_INSTANCED) {
+ has_instanced_panel = true;
+ continue;
+ }
+
+ if (use_category_tabs) {
+ if (panel_type->category[0] && !STREQ(category, panel_type->category)) {
+ continue;
+ }
+ }
+
+ /* We start property search with an empty panel list, so there's
+ * no point in trying to find an existing panel with this type. */
+ has_result = panel_property_search(C, region, style, NULL, panel_type, search_filter);
+ if (has_result) {
+ break;
+ }
+ }
+
+ /* Run property search for instanced panels (created in the layout calls of previous panels). */
+ if (!has_result && has_instanced_panel) {
+ LISTBASE_FOREACH (Panel *, panel, &region->panels) {
+ /* Note that these checks are duplicated from #ED_region_panels_layout_ex. */
+ if (panel->type == NULL || !(panel->type->flag & PNL_INSTANCED)) {
+ continue;
+ }
+ if (use_category_tabs) {
+ if (panel->type->category[0] && !STREQ(category, panel->type->category)) {
+ continue;
+ }
+ }
+
+ has_result = panel_property_search(C, region, style, panel, panel->type, search_filter);
+ if (has_result) {
+ break;
+ }
+ }
+ }
+
+ /* Free the panels and blocks, as they are only used for search. */
+ UI_blocklist_free(C, &region->uiblocks);
+ UI_panels_free_instanced(C, region);
+ BKE_area_region_panels_free(&region->panels);
+
+ return has_result;
+}
+
void ED_region_header_layout(const bContext *C, ARegion *region)
{
const uiStyle *style = UI_style_get_dpi();
diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h
index a5419fea5ca..0a0846cf216 100644
--- a/source/blender/editors/space_buttons/buttons_intern.h
+++ b/source/blender/editors/space_buttons/buttons_intern.h
@@ -23,6 +23,7 @@
#pragma once
+#include "BLI_bitmap.h"
#include "DNA_listBase.h"
#include "RNA_types.h"
@@ -37,6 +38,16 @@ struct bNodeTree;
struct uiLayout;
struct wmOperatorType;
+struct SpaceProperties_Runtime {
+ /** For filtering properties displayed in the space. */
+ char search_string[UI_MAX_NAME_STR];
+ /**
+ * Bitfield (in the same order as the tabs) for whether each tab has properties
+ * that match the search filter. Only valid when #search_string is set.
+ */
+ BLI_bitmap *tab_search_results;
+};
+
/* context data */
typedef struct ButsContextPath {
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 8c1030f6fc4..e7f057683ab 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -26,6 +26,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -48,6 +49,7 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "UI_interface.h"
#include "UI_resources.h"
#include "buttons_intern.h" /* own include */
@@ -110,7 +112,10 @@ static void buttons_free(SpaceLink *sl)
MEM_freeN(ct);
}
- MEM_SAFE_FREE(sbuts->runtime);
+ if (sbuts->runtime != NULL) {
+ MEM_SAFE_FREE(sbuts->runtime->tab_search_results);
+ MEM_freeN(sbuts->runtime);
+ }
}
/* spacetype; init callback */
@@ -121,6 +126,7 @@ static void buttons_init(struct wmWindowManager *UNUSED(wm), ScrArea *area)
if (sbuts->runtime == NULL) {
sbuts->runtime = MEM_mallocN(sizeof(SpaceProperties_Runtime), __func__);
sbuts->runtime->search_string[0] = '\0';
+ sbuts->runtime->tab_search_results = BLI_BITMAP_NEW(BCONTEXT_TOT * 2, __func__);
}
}
@@ -135,6 +141,7 @@ static SpaceLink *buttons_duplicate(SpaceLink *sl)
if (sfile_old->runtime != NULL) {
sbutsn->runtime = MEM_dupallocN(sfile_old->runtime);
sbutsn->runtime->search_string[0] = '\0';
+ sbutsn->runtime->tab_search_results = BLI_BITMAP_NEW(BCONTEXT_TOT, __func__);
}
return (SpaceLink *)sbutsn;
@@ -298,6 +305,163 @@ static void buttons_main_region_layout_properties(const bContext *C,
ED_region_panels_layout_ex(C, region, &region->type->paneltypes, contexts, NULL);
}
+const char *ED_buttons_search_string_get(SpaceProperties *sbuts)
+{
+ return sbuts->runtime->search_string;
+}
+
+int ED_buttons_search_string_length(struct SpaceProperties *sbuts)
+{
+ return BLI_strnlen(sbuts->runtime->search_string, sizeof(sbuts->runtime->search_string));
+}
+
+void ED_buttons_search_string_set(SpaceProperties *sbuts, const char *value)
+{
+ BLI_strncpy(sbuts->runtime->search_string, value, sizeof(sbuts->runtime->search_string));
+}
+
+bool ED_buttons_tab_has_search_result(SpaceProperties *sbuts, const int index)
+{
+ return BLI_BITMAP_TEST(sbuts->runtime->tab_search_results, index);
+}
+
+static bool property_search_for_context(const bContext *C, ARegion *region, SpaceProperties *sbuts)
+{
+ const char *contexts[2] = {buttons_main_region_context_string(sbuts->mainb), NULL};
+
+ if (sbuts->mainb == BCONTEXT_TOOL) {
+ return false;
+ }
+
+ buttons_context_compute(C, sbuts);
+ return ED_region_property_search(C, region, &region->type->paneltypes, contexts, NULL);
+}
+
+static void property_search_move_to_next_tab_with_results(SpaceProperties *sbuts,
+ const short *context_tabs_array,
+ const int tabs_len)
+{
+ /* As long as all-tab search in the tool is disabled in the tool context, don't move from it. */
+ if (sbuts->mainb == BCONTEXT_TOOL) {
+ return;
+ }
+
+ int current_tab_index = 0;
+ for (int i = 0; i < tabs_len; i++) {
+ if (sbuts->mainb == context_tabs_array[i]) {
+ current_tab_index = i;
+ break;
+ }
+ }
+
+ /* Try the tabs after the current tab. */
+ for (int i = current_tab_index; i < tabs_len; i++) {
+ if (BLI_BITMAP_TEST(sbuts->runtime->tab_search_results, i)) {
+ sbuts->mainbuser = context_tabs_array[i];
+ return;
+ }
+ }
+
+ /* Try the tabs before the current tab. */
+ for (int i = 0; i < current_tab_index; i++) {
+ if (BLI_BITMAP_TEST(sbuts->runtime->tab_search_results, i)) {
+ sbuts->mainbuser = context_tabs_array[i];
+ return;
+ }
+ }
+}
+
+static void property_search_all_tabs(const bContext *C,
+ SpaceProperties *sbuts,
+ ARegion *main_region,
+ const short *context_tabs_array,
+ const int tabs_len)
+{
+ /* Use local copies of the area and duplicate the region as a mainly-paranoid protection
+ * against changing any of the space / region data while running the search. */
+ ScrArea area_copy = *CTX_wm_area(C);
+ ARegion *region_copy = BKE_area_region_copy(area_copy.type, main_region);
+ bContext *C_copy = CTX_copy(C);
+ CTX_wm_area_set(C_copy, &area_copy);
+ CTX_wm_region_set(C_copy, region_copy);
+ SpaceProperties sbuts_copy = *sbuts;
+ sbuts_copy.path = NULL;
+ sbuts_copy.texuser = NULL;
+ sbuts_copy.runtime = MEM_dupallocN(sbuts->runtime);
+ sbuts_copy.runtime->tab_search_results = NULL;
+ area_copy.spacedata.first = &sbuts_copy;
+
+ /* Loop through the tabs added to the properties editor. */
+ for (int i = 0; i < tabs_len; i++) {
+ /* -1 corresponds to a spacer. */
+ if (context_tabs_array[i] == -1) {
+ continue;
+ }
+
+ /* Handle search for the current tab in the normal layout pass. */
+ if (context_tabs_array[i] == sbuts->mainb) {
+ continue;
+ }
+
+ sbuts_copy.mainb = sbuts_copy.mainbo = sbuts_copy.mainbuser = context_tabs_array[i];
+
+ /* Actually do the search and store the result in the bitmap. */
+ BLI_BITMAP_SET(sbuts->runtime->tab_search_results,
+ i,
+ property_search_for_context(C_copy, region_copy, &sbuts_copy));
+
+ UI_blocklist_free(C_copy, &region_copy->uiblocks);
+ }
+
+ BKE_area_region_free(area_copy.type, region_copy);
+ MEM_freeN(region_copy);
+ buttons_free((SpaceLink *)&sbuts_copy);
+ MEM_freeN(C_copy);
+}
+
+/**
+ * Handle property search for the layout pass, including finding which tabs have
+ * search results and switching if the current tab doesn't have a result.
+ */
+static void buttons_main_region_property_search(const bContext *C,
+ SpaceProperties *sbuts,
+ ARegion *region)
+{
+ /* Theoretical maximum of every context shown with a spacer between every tab. */
+ short context_tabs_array[BCONTEXT_TOT * 2];
+ int tabs_len = ED_buttons_tabs_list(sbuts, context_tabs_array);
+
+ property_search_all_tabs(C, sbuts, region, context_tabs_array, tabs_len);
+
+ /* Check whether the current tab has a search match. */
+ bool current_tab_has_search_match = false;
+ LISTBASE_FOREACH (Panel *, panel, &region->panels) {
+ if (UI_panel_is_active(panel) && UI_panel_matches_search_filter(panel)) {
+ current_tab_has_search_match = true;
+ }
+ }
+
+ /* Find which index in the list the current tab corresponds to. */
+ int current_tab_index = -1;
+ for (int i = 0; i < tabs_len; i++) {
+ if (context_tabs_array[i] == sbuts->mainb) {
+ current_tab_index = i;
+ }
+ }
+ BLI_assert(current_tab_index != -1);
+
+ /* Update the tab search match flag for the current tab. */
+ BLI_BITMAP_SET(
+ sbuts->runtime->tab_search_results, current_tab_index, current_tab_has_search_match);
+
+ /* Move to the next tab with a result */
+ if (!current_tab_has_search_match) {
+ if (region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) {
+ property_search_move_to_next_tab_with_results(sbuts, context_tabs_array, tabs_len);
+ }
+ }
+}
+
static void buttons_main_region_layout(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
@@ -310,6 +474,10 @@ static void buttons_main_region_layout(const bContext *C, ARegion *region)
buttons_main_region_layout_properties(C, sbuts, region);
}
+ if (region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE) {
+ buttons_main_region_property_search(C, sbuts, region);
+ }
+
sbuts->mainbo = sbuts->mainb;
}
@@ -722,8 +890,8 @@ void ED_spacetype_buttons(void)
buttons_context_register(art);
BLI_addhead(&st->regiontypes, art);
- /* Register the panel types from modifiers. The actual panels are built per modifier rather than
- * per modifier type. */
+ /* Register the panel types from modifiers. The actual panels are built per modifier rather
+ * than per modifier type. */
for (ModifierType i = 0; i < NUM_MODIFIER_TYPES; i++) {
const ModifierTypeInfo *mti = BKE_modifier_get_info(i);
if (mti != NULL && mti->panelRegister != NULL) {
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 9d9b41a1f81..be02e450412 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -56,6 +56,9 @@ struct bNodeTree;
struct wmOperator;
struct wmTimer;
+/* Defined in `buttons_intern.h`. */
+typedef struct SpaceProperties_Runtime SpaceProperties_Runtime;
+
/* TODO 2.8: We don't write the global areas to files currently. Uncomment
* define to enable writing (should become the default in a bit). */
//#define WITH_GLOBAL_AREA_WRITING
@@ -129,13 +132,6 @@ typedef enum eSpaceInfo_RptMask {
/** \name Properties Editor
* \{ */
-#
-#
-typedef struct SpaceProperties_Runtime {
- /** For filtering properties displayed in the space. Length defined as UI_MAX_NAME_STR. */
- char search_string[128];
-} SpaceProperties_Runtime;
-
/* Properties Editor */
typedef struct SpaceProperties {
SpaceLink *next, *prev;
@@ -168,7 +164,7 @@ typedef struct SpaceProperties {
void *texuser;
/* Doesn't necessarily need to be a pointer, but runtime structs are still written to files. */
- SpaceProperties_Runtime *runtime;
+ struct SpaceProperties_Runtime *runtime;
} SpaceProperties;
/* button defines (deprecated) */
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 2a4bc6bae06..5b34281ffa0 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -1825,6 +1825,53 @@ static void rna_SpaceProperties_context_update(Main *UNUSED(bmain),
}
}
+static int rna_SpaceProperties_tab_search_results_getlength(PointerRNA *ptr,
+ int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ SpaceProperties *sbuts = ptr->data;
+
+ short context_tabs_array[BCONTEXT_TOT * 2]; /* Dummy variable. */
+ const int tabs_len = ED_buttons_tabs_list(sbuts, context_tabs_array);
+
+ length[0] = tabs_len;
+
+ return length[0];
+}
+
+static void rna_SpaceProperties_tab_search_results_get(PointerRNA *ptr, bool *values)
+{
+ SpaceProperties *sbuts = ptr->data;
+
+ short context_tabs_array[BCONTEXT_TOT * 2]; /* Dummy variable. */
+ const int tabs_len = ED_buttons_tabs_list(sbuts, context_tabs_array);
+
+ for (int i = 0; i < tabs_len; i++) {
+ values[i] = ED_buttons_tab_has_search_result(sbuts, i);
+ }
+}
+
+static void rna_SpaceProperties_search_filter_get(PointerRNA *ptr, char *value)
+{
+ SpaceProperties *sbuts = ptr->data;
+ const char *search_filter = ED_buttons_search_string_get(sbuts);
+
+ strcpy(value, search_filter);
+}
+
+static int rna_SpaceProperties_search_filter_length(PointerRNA *ptr)
+{
+ SpaceProperties *sbuts = ptr->data;
+
+ return ED_buttons_search_string_length(sbuts);
+}
+
+static void rna_SpaceProperties_search_filter_set(struct PointerRNA *ptr, const char *value)
+{
+ SpaceProperties *sbuts = ptr->data;
+
+ ED_buttons_search_string_set(sbuts, value);
+}
+
static void rna_SpaceProperties_search_filter_update(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
@@ -4514,8 +4561,23 @@ static void rna_def_space_properties(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Pin ID", "Use the pinned context");
/* Property search. */
+
+ prop = RNA_def_property(srna, "tab_search_results", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_array(prop, 0); /* Dynamic length, see next line. */
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_boolean_funcs(prop, "rna_SpaceProperties_tab_search_results_get", NULL);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_SpaceProperties_tab_search_results_getlength");
+ RNA_def_property_ui_text(
+ prop, "Tab Search Results", "Whether or not each visible tab has a search result");
+
prop = RNA_def_property(srna, "search_filter", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "runtime->search_string");
+ /* The search filter is stored in the property editor's runtime struct which
+ * is only defined in an internal header, so use the getter / setter here. */
+ RNA_def_property_string_funcs(prop,
+ "rna_SpaceProperties_search_filter_get",
+ "rna_SpaceProperties_search_filter_length",
+ "rna_SpaceProperties_search_filter_set");
RNA_def_property_ui_text(prop, "Display Filter", "Live search filtering string");
RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
RNA_def_property_update(