diff options
-rw-r--r-- | source/blender/editors/include/ED_screen.h | 5 | ||||
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 3 | ||||
-rw-r--r-- | source/blender/editors/interface/interface.c | 5 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_layout.c | 6 | ||||
-rw-r--r-- | source/blender/editors/screen/area.c | 263 | ||||
-rw-r--r-- | source/blender/editors/space_buttons/space_buttons.c | 163 |
6 files changed, 298 insertions, 147 deletions
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 1e6f3ed3af1..dfdce21614c 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -91,6 +91,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 fe0a57f26ea..6655db3395c 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -674,7 +674,6 @@ enum { void UI_block_theme_style_set(uiBlock *block, char theme_style); char UI_block_emboss_get(uiBlock *block); void UI_block_emboss_set(uiBlock *block, char emboss); -bool UI_block_has_search_filter(const uiBlock *block); bool UI_block_is_search_only(const uiBlock *block); void UI_block_set_search_only(uiBlock *block, bool search_only); void UI_block_set_search_filter(uiBlock *block, const char *search_filter); @@ -1874,7 +1873,7 @@ uiLayout *UI_block_layout(uiBlock *block, 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_apply_search_filter(uiBlock *block); +bool UI_block_apply_search_filter(uiBlock *block); void UI_region_message_subscribe(struct ARegion *region, struct wmMsgBus *mbus); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 98140a2c058..8aa25100b0b 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -3509,11 +3509,6 @@ void UI_block_theme_style_set(uiBlock *block, char theme_style) block->theme_style = theme_style; } -bool UI_block_has_search_filter(const uiBlock *block) -{ - return block->search_filter != NULL && block->search_filter[0] != '\0'; -} - bool UI_block_is_search_only(const uiBlock *block) { return block->flag & UI_BLOCK_SEARCH_ONLY; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index b528f9e29b2..2310eca777d 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -5307,10 +5307,10 @@ static void block_search_deactivate_buttons(uiBlock *block) * * \note Must be run before #UI_block_layout_resolve. */ -void UI_block_apply_search_filter(uiBlock *block) +bool UI_block_apply_search_filter(uiBlock *block) { if (!(block->search_filter && block->search_filter[0])) { - return; + return false; } const bool panel_label_matches = block_search_panel_label_matches(block); @@ -5326,6 +5326,8 @@ void UI_block_apply_search_filter(uiBlock *block) if (!panel_label_matches) { block_search_deactivate_buttons(block); } + + return has_result; } /** \} */ diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 171d6105547..e4dccea279e 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2610,6 +2610,8 @@ static void ed_panel_draw(const bContext *C, bool open; panel = UI_panel_begin(region, lb, block, pt, panel, &open); + const bool search_filter_active = search_filter != NULL && search_filter[0] != '\0'; + /* bad fixed values */ int xco, yco, h = 0; int headerend = w - UI_UNIT_X; @@ -2670,7 +2672,7 @@ static void ed_panel_draw(const bContext *C, panel->labelofs = 0; } - if (open || UI_block_has_search_filter(block) || search_only) { + if (open || search_filter_active) { short panelContext; /* panel context can either be toolbar region or normal panels region */ @@ -2710,7 +2712,7 @@ static void ed_panel_draw(const bContext *C, UI_block_end(C, block); /* Draw child panels. */ - if (open || UI_block_has_search_filter(block)) { + if (open || search_filter_active) { LISTBASE_FOREACH (LinkData *, link, &pt->children) { PanelType *child_pt = link->data; Panel *child_panel = UI_panel_find_by_type(&panel->children, child_pt); @@ -2734,6 +2736,79 @@ static void ed_panel_draw(const bContext *C, } /** + * Check whether a panel should be added to the region's panel layout. + */ +static bool panel_add_check(const bContext *C, + const WorkSpace *workspace, + const char *contexts[], + const char *category_override, + PanelType *panel_type) +{ + /* Only add top level panels. */ + if (panel_type->parent) { + return false; + } + /* Check the category override first. */ + if (category_override) { + if (!STREQ(panel_type->category, category_override)) { + return false; + } + } + + /* Verify context. */ + if (contexts != NULL && panel_type->context[0]) { + if (!streq_array_any(panel_type->context, contexts)) { + return false; + } + } + + /* If we're tagged, only use compatible. */ + if (panel_type->owner_id[0]) { + if (!BKE_workspace_owner_id_check(workspace, panel_type->owner_id)) { + return false; + } + } + + if (LIKELY(panel_type->draw)) { + if (panel_type->poll && !panel_type->poll(C, panel_type)) { + return false; + } + } + + return true; +} + +static bool region_uses_category_tabs(const ScrArea *area, const ARegion *region) +{ + return ((1 << region->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) || + (region->regiontype == RGN_TYPE_TOOLS && area->spacetype == SPACE_CLIP); +} + +static const char *region_panels_collect_categories(ARegion *region, + LinkNode *panel_types_stack, + bool *use_category_tabs) +{ + UI_panel_category_clear_all(region); + + /* gather unique categories */ + for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) { + PanelType *pt = pt_link->link; + if (pt->category[0]) { + if (!UI_panel_category_find(region, pt->category)) { + UI_panel_category_add(region, pt->category); + } + } + } + + if (UI_panel_category_is_visible(region)) { + return UI_panel_category_active_get(region, true); + } + + *use_category_tabs = false; + return NULL; +} + +/** * \param contexts: A NULL terminated array of context strings to match against. * Matching against any of these strings will draw the panel. * Can be NULL to skip context checks. @@ -2748,29 +2823,7 @@ void ED_region_panels_layout_ex(const bContext *C, WorkSpace *workspace = CTX_wm_workspace(C); LinkNode *panel_types_stack = NULL; LISTBASE_FOREACH_BACKWARD (PanelType *, pt, paneltypes) { - /* Only draw top level panels. */ - if (pt->parent) { - continue; - } - - if (category_override) { - if (!STREQ(pt->category, category_override)) { - continue; - } - } - - /* verify context */ - if (contexts && pt->context[0] && !streq_array_any(pt->context, contexts)) { - continue; - } - - /* If we're tagged, only use compatible. */ - if (pt->owner_id[0] && BKE_workspace_owner_id_check(workspace, pt->owner_id) == false) { - continue; - } - - /* draw panel */ - if (pt->draw && (!pt->poll || pt->poll(C, pt))) { + if (panel_add_check(C, workspace, contexts, category_override, pt)) { BLI_linklist_prepend_alloca(&panel_types_stack, pt); } } @@ -2783,10 +2836,7 @@ void ED_region_panels_layout_ex(const bContext *C, /* XXX, should use some better check? */ /* For now also has hardcoded check for clip editor until it supports actual toolbar. */ - bool use_category_tabs = (category_override == NULL) && - ((((1 << region->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) || - (region->regiontype == RGN_TYPE_TOOLS && - area->spacetype == SPACE_CLIP))); + bool use_category_tabs = (category_override == NULL) && region_uses_category_tabs(area, region); /* offset panels for small vertical tab area */ const char *category = NULL; const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH; @@ -2802,25 +2852,10 @@ void ED_region_panels_layout_ex(const bContext *C, /* collect categories */ if (use_category_tabs) { - UI_panel_category_clear_all(region); - - /* gather unique categories */ - for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) { - PanelType *pt = pt_link->link; - if (pt->category[0]) { - if (!UI_panel_category_find(region, pt->category)) { - UI_panel_category_add(region, pt->category); - } - } - } - - if (!UI_panel_category_is_visible(region)) { - use_category_tabs = false; - } - else { - category = UI_panel_category_active_get(region, true); - margin_x = category_tabs_width; - } + category = region_panels_collect_categories(region, panel_types_stack, &use_category_tabs); + } + if (use_category_tabs) { + margin_x = category_tabs_width; } w = BLI_rctf_size_x(&v2d->cur); @@ -3034,6 +3069,138 @@ void ED_region_panels_init(wmWindowManager *wm, ARegion *region) WM_event_add_keymap_handler(®ion->handlers, keymap); } +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); + UI_block_set_search_filter(block, search_filter); + + if (panel == NULL) { + bool open; + panel = UI_panel_begin(region, ®ion->panels, block, panel_type, panel, &open); + } + + /* Check after each layout to increase the likelyhood of returning early. */ + 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); + uiLayoutRootSetSearchOnly(panel->layout, true); + panel_type->draw_header_preset(C, panel); + if (UI_block_apply_search_filter(block)) { + return true; + } + } + + if (panel->type->draw_header != NULL) { + panel->layout = UI_block_layout( + block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, 0, 0, 0, 0, 0, style); + uiLayoutRootSetSearchOnly(panel->layout, true); + panel_type->draw_header(C, panel); + if (UI_block_apply_search_filter(block)) { + return true; + } + } + + if (LIKELY(panel->type->draw != NULL)) { + panel->layout = UI_block_layout( + block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 0, 0, 0, style); + uiLayoutRootSetSearchOnly(panel->layout, true); + panel_type->draw(C, panel); + if (UI_block_apply_search_filter(block)) { + return true; + } + } + + LISTBASE_FOREACH (LinkData *, link, &panel_type->children) { + PanelType *panel_type_child = link->data; + if (LIKELY(panel->type->draw != NULL)) { + if (!panel_type_child->poll || panel_type_child->poll(C, panel_type_child)) { + if (panel_property_search(C, region, style, NULL, panel_type_child, search_filter)) { + return true; + } + } + } + } + + return false; +} + +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_search_filter_get(CTX_wm_area(C), 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); + } + + 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; + + 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; + } + } + + has_result = panel_property_search(C, region, style, NULL, panel_type, search_filter); + if (has_result) { + break; + } + } + + if (!has_result && has_instanced_panel) { + LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { + 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; + } + } + } + + UI_blocklist_free(C, ®ion->uiblocks); + UI_panels_free_instanced(C, region); + BKE_area_region_panels_free(®ion->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/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 2cb706b97f6..cd31598b0e6 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -232,80 +232,70 @@ int ED_buttons_tabs_list(SpaceProperties *sbuts, int *context_tabs_array) return length; } -static void buttons_main_region_layout_properties(const bContext *C, - SpaceProperties *sbuts, - ARegion *region) +static const char *buttons_main_region_context_string(const short mainb) { - buttons_context_compute(C, sbuts); - - const char *contexts[2] = {NULL, NULL}; - - switch (sbuts->mainb) { + switch (mainb) { case BCONTEXT_SCENE: - contexts[0] = "scene"; - break; + return "scene"; case BCONTEXT_RENDER: - contexts[0] = "render"; - break; + return "render"; case BCONTEXT_OUTPUT: - contexts[0] = "output"; - break; + return "output"; case BCONTEXT_VIEW_LAYER: - contexts[0] = "view_layer"; - break; + return "view_layer"; case BCONTEXT_WORLD: - contexts[0] = "world"; - break; + return "world"; case BCONTEXT_OBJECT: - contexts[0] = "object"; - break; + return "object"; case BCONTEXT_DATA: - contexts[0] = "data"; - break; + return "data"; case BCONTEXT_MATERIAL: - contexts[0] = "material"; - break; + return "material"; case BCONTEXT_TEXTURE: - contexts[0] = "texture"; - break; + return "texture"; case BCONTEXT_PARTICLE: - contexts[0] = "particle"; - break; + return "particle"; case BCONTEXT_PHYSICS: - contexts[0] = "physics"; - break; + return "physics"; case BCONTEXT_BONE: - contexts[0] = "bone"; - break; + return "bone"; case BCONTEXT_MODIFIER: - contexts[0] = "modifier"; - break; + return "modifier"; case BCONTEXT_SHADERFX: - contexts[0] = "shaderfx"; - break; + return "shaderfx"; case BCONTEXT_CONSTRAINT: - contexts[0] = "constraint"; - break; + return "constraint"; case BCONTEXT_BONE_CONSTRAINT: - contexts[0] = "bone_constraint"; - break; + return "bone_constraint"; case BCONTEXT_TOOL: - contexts[0] = "tool"; - break; + return "tool"; } + /* All the cases should be handled. */ + BLI_assert(false); + return ""; +} + +static void buttons_main_region_layout_properties(const bContext *C, + SpaceProperties *sbuts, + ARegion *region) +{ + buttons_context_compute(C, sbuts); + + const char *contexts[2] = {buttons_main_region_context_string(sbuts->mainb), NULL}; + ED_region_panels_layout_ex(C, region, ®ion->type->paneltypes, contexts, NULL); } -static void main_region_layout_current_context(const bContext *C, - SpaceProperties *sbuts, - ARegion *region) +static bool property_search_for_context(const bContext *C, ARegion *region, const short mainb) { - if (sbuts->mainb == BCONTEXT_TOOL) { - ED_view3d_buttons_region_layout_ex(C, region, "Tool"); + const char *contexts[2] = {buttons_main_region_context_string(mainb), NULL}; + + if (mainb == BCONTEXT_TOOL) { + return false; } else { - buttons_main_region_layout_properties(C, sbuts, region); + return ED_region_property_search(C, region, ®ion->type->paneltypes, contexts, NULL); } } @@ -340,66 +330,41 @@ static void property_search_move_to_next_tab_with_results(SpaceProperties *sbuts static void property_search_all_tabs(const bContext *C, SpaceProperties *sbuts, - ARegion *main_region) + ARegion *main_region, + const int *context_tabs_array, + const int tabs_len) { sbuts->context_search_filter_active = 0; /* Duplicate space and region so we don't change any data for this space. */ ScrArea *area_copy = MEM_dupallocN(CTX_wm_area(C)); ARegion *region_copy = BKE_area_region_copy(CTX_wm_area(C)->type, main_region); - BKE_area_region_panels_free(®ion_copy->panels); + BLI_listbase_clear(®ion_copy->panels); 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 = MEM_dupallocN(sbuts); - int context_tabs_array[32]; - int tabs_tot = ED_buttons_tabs_list(sbuts, context_tabs_array); - - bool current_tab_has_search_match = false; - /* Loop through the tabs added to the properties editor. */ - for (int i = 0; i < tabs_tot; i++) { + for (int i = 0; i < tabs_len; i++) { + /* -1 corresponds to a spacer. */ if (context_tabs_array[i] == -1) { continue; } - /* Run the layout with this tab set active. */ - sbuts_copy->mainb = sbuts->mainbo = sbuts_copy->mainbuser = context_tabs_array[i]; - - /* Run the layout for the actual region if the tab matches to avoid doing it again later on. */ - const bool use_actual_region = sbuts->mainb == sbuts_copy->mainb; - if (use_actual_region) { - main_region_layout_current_context(C, sbuts, main_region); - } - else { - main_region_layout_current_context(C_copy, sbuts_copy, region_copy); - } - - /* Store whether this tab has any unfiltered panels left. */ - bool tab_has_search_match = false; - LISTBASE_FOREACH ( - Panel *, panel, use_actual_region ? &main_region->panels : ®ion_copy->panels) { - tab_has_search_match |= UI_panel_matches_search_filter(panel) && UI_panel_is_active(panel); - } - if (tab_has_search_match) { - sbuts->context_search_filter_active |= (1 << i); - if (use_actual_region) { - current_tab_has_search_match = tab_has_search_match; - } + /* Handle search for the current tab later in the normal layout pass. */ + if (context_tabs_array[i] == sbuts->mainb) { + continue; } - /* Free data created during the layout process. */ - UI_region_panels_remove_handlers(C_copy, region_copy); - BKE_area_region_panels_free(®ion_copy->panels); - UI_blocklist_free(C_copy, ®ion_copy->uiblocks); - } + sbuts_copy->mainb = sbuts->mainbo = sbuts_copy->mainbuser = context_tabs_array[i]; - if (!current_tab_has_search_match && main_region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) { - property_search_move_to_next_tab_with_results(sbuts, context_tabs_array, tabs_tot); + SET_FLAG_FROM_TEST(sbuts->context_search_filter_active, + property_search_for_context(C_copy, region_copy, sbuts_copy->mainb), + (1 << i)); } - BKE_area_region_free(CTX_wm_area(C_copy)->type, region_copy); + BKE_area_region_free(area_copy->type, region_copy); MEM_freeN(region_copy); MEM_freeN(sbuts_copy); MEM_freeN(area_copy); @@ -411,11 +376,29 @@ static void buttons_main_region_layout(const bContext *C, ARegion *region) /* draw entirely, view changes should be handled here */ SpaceProperties *sbuts = CTX_wm_space_properties(C); - if (region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE) { - property_search_all_tabs(C, sbuts, region); + if (sbuts->mainb == BCONTEXT_TOOL) { + ED_view3d_buttons_region_layout_ex(C, region, "Tool"); } else { - main_region_layout_current_context(C, sbuts, region); + buttons_main_region_layout_properties(C, sbuts, region); + } + + if (region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE) { + int context_tabs_array[32]; + int tabs_len = ED_buttons_tabs_list(sbuts, context_tabs_array); + + property_search_all_tabs(C, sbuts, region, context_tabs_array, tabs_len); + + bool current_tab_has_search_match = false; + LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { + if (UI_panel_is_active(panel) && UI_panel_matches_search_filter(panel)) { + current_tab_has_search_match = true; + } + } + + if (!current_tab_has_search_match && region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) { + property_search_move_to_next_tab_with_results(sbuts, context_tabs_array, tabs_len); + } } sbuts->mainbo = sbuts->mainb; |