Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/interface/interface_panel.c
| Show First 20 Lines • Show All 187 Lines • ▼ Show 20 Lines | LISTBASE_FOREACH (Panel *, panel, lb) { | ||||
| if ((panel->runtime_flag & PANEL_ANIM_ALIGN) && !(*r_panel_animation)) { | if ((panel->runtime_flag & PANEL_ANIM_ALIGN) && !(*r_panel_animation)) { | ||||
| *r_panel_animation = panel; | *r_panel_animation = panel; | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| static bool panels_need_realign(ScrArea *area, ARegion *region, Panel **r_panel_animation) | /** | ||||
| * \return True if the properties editor switch tabs since the last layout pass. | |||||
| */ | |||||
| static bool properties_space_needs_realign(ScrArea *area, ARegion *region) | |||||
| { | { | ||||
| *r_panel_animation = NULL; | |||||
| if (area->spacetype == SPACE_PROPERTIES && region->regiontype == RGN_TYPE_WINDOW) { | if (area->spacetype == SPACE_PROPERTIES && region->regiontype == RGN_TYPE_WINDOW) { | ||||
| SpaceProperties *sbuts = area->spacedata.first; | SpaceProperties *sbuts = area->spacedata.first; | ||||
| if (sbuts->mainbo != sbuts->mainb) { | if (sbuts->mainbo != sbuts->mainb) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| return false; | |||||
| } | |||||
| static bool panels_need_realign(ScrArea *area, ARegion *region, Panel **r_panel_animation) | |||||
| { | |||||
| *r_panel_animation = NULL; | |||||
| if (properties_space_needs_realign(area, region)) { | |||||
| return true; | |||||
| } | |||||
| /* Detect if a panel was added or removed. */ | /* Detect if a panel was added or removed. */ | ||||
| Panel *panel_animation = NULL; | Panel *panel_animation = NULL; | ||||
| bool no_animation = false; | bool no_animation = false; | ||||
| if (panel_active_animation_changed(®ion->panels, &panel_animation, &no_animation)) { | if (panel_active_animation_changed(®ion->panels, &panel_animation, &no_animation)) { | ||||
Severin: Noticed these checks are out-dated, so I removed them rBe839179b014a. | |||||
| return true; | return true; | ||||
| } | } | ||||
| /* Detect panel marked for animation, if we're not already animating. */ | /* Detect panel marked for animation, if we're not already animating. */ | ||||
| if (panel_animation) { | if (panel_animation) { | ||||
| if (!no_animation) { | if (!no_animation) { | ||||
| *r_panel_animation = panel_animation; | *r_panel_animation = panel_animation; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 453 Lines • ▼ Show 20 Lines | if (newpanel) { | ||||
| BLI_addtail(lb, panel); | BLI_addtail(lb, panel); | ||||
| } | } | ||||
| else { | else { | ||||
| /* Panel already exists. */ | /* Panel already exists. */ | ||||
| panel->type = pt; | panel->type = pt; | ||||
| } | } | ||||
| panel->runtime.block = block; | |||||
| /* Do not allow closed panels without headers! Else user could get "disappeared" UI! */ | /* Do not allow closed panels without headers! Else user could get "disappeared" UI! */ | ||||
| if ((pt->flag & PNL_NO_HEADER) && (panel->flag & PNL_CLOSED)) { | if ((pt->flag & PNL_NO_HEADER) && (panel->flag & PNL_CLOSED)) { | ||||
| panel->flag &= ~PNL_CLOSED; | panel->flag &= ~PNL_CLOSED; | ||||
| /* Force update of panels' positions. */ | /* Force update of panels' positions. */ | ||||
| panel->sizex = 0; | panel->sizex = 0; | ||||
| panel->sizey = 0; | panel->sizey = 0; | ||||
| panel->blocksizex = 0; | panel->blocksizex = 0; | ||||
| panel->blocksizey = 0; | panel->blocksizey = 0; | ||||
| Show All 38 Lines | if (panel->flag & PNL_CLOSED) { | ||||
| return panel; | return panel; | ||||
| } | } | ||||
| *r_open = true; | *r_open = true; | ||||
| return panel; | return panel; | ||||
| } | } | ||||
| /** | |||||
| * Create the panel header button group, used to mark which buttons are part of | |||||
| * panel headers for later panel search handling. Should be called before adding | |||||
| * buttons for the panel's header layout. | |||||
| */ | |||||
| void UI_panel_header_buttons_begin(Panel *panel) | |||||
| { | |||||
| uiBlock *block = panel->runtime.block; | |||||
| ui_block_new_button_group(block, UI_BUTTON_GROUP_LOCK | UI_BUTTON_GROUP_PANEL_HEADER); | |||||
| } | |||||
| /** | |||||
| * Allow new button groups to be created after the header group. | |||||
| */ | |||||
| void UI_panel_header_buttons_end(Panel *panel) | |||||
| { | |||||
| uiBlock *block = panel->runtime.block; | |||||
| /* There should always be the button group created in #UI_panel_header_buttons_begin. */ | |||||
| BLI_assert(!BLI_listbase_is_empty(&block->button_groups)); | |||||
| uiButtonGroup *button_group = block->button_groups.last; | |||||
| /* Repurpose the first "header" button group if it is empty, in case the first button added to | |||||
| * the panel doesn't add a new group (if the button is created directly rather than through an | |||||
| * interface layout call). */ | |||||
| if (BLI_listbase_count(&block->button_groups) == 1 && | |||||
| BLI_listbase_is_empty(&button_group->buttons)) { | |||||
| button_group->flag &= ~UI_BUTTON_GROUP_PANEL_HEADER; | |||||
| } | |||||
| button_group->flag &= ~UI_BUTTON_GROUP_LOCK; | |||||
| } | |||||
| static float panel_region_offset_x_get(const ARegion *region) | static float panel_region_offset_x_get(const ARegion *region) | ||||
| { | { | ||||
| if (UI_panel_category_is_visible(region)) { | if (UI_panel_category_is_visible(region)) { | ||||
| if (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) != RGN_ALIGN_RIGHT) { | if (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) != RGN_ALIGN_RIGHT) { | ||||
| return UI_PANEL_CATEGORY_MARGIN_WIDTH; | return UI_PANEL_CATEGORY_MARGIN_WIDTH; | ||||
| } | } | ||||
| } | } | ||||
| return 0; | return 0.0f; | ||||
| } | } | ||||
| void UI_panel_end(const ARegion *region, uiBlock *block, int width, int height, bool open) | /** | ||||
| * Starting from the "block size" set in #UI_panel_end, calculate the full size | |||||
| * of the panel including the subpanel headers and buttons. | |||||
| */ | |||||
| static void panel_calculate_size_recursive(ARegion *region, Panel *panel) | |||||
| { | { | ||||
| Panel *panel = block->panel; | int width = panel->blocksizex; | ||||
| int height = panel->blocksizey; | |||||
| /* Set panel size excluding children. */ | |||||
| panel->blocksizex = width; | |||||
| panel->blocksizey = height; | |||||
| /* Compute total panel size including children. */ | LISTBASE_FOREACH (Panel *, child_panel, &panel->children) { | ||||
| LISTBASE_FOREACH (Panel *, pachild, &panel->children) { | if (child_panel->runtime_flag & PANEL_ACTIVE) { | ||||
| if (pachild->runtime_flag & PANEL_ACTIVE) { | panel_calculate_size_recursive(region, child_panel); | ||||
| width = max_ii(width, pachild->sizex); | width = max_ii(width, child_panel->sizex); | ||||
| height += get_panel_real_size_y(pachild); | height += get_panel_real_size_y(child_panel); | ||||
| } | } | ||||
| } | } | ||||
| /* Update total panel size. */ | /* Update total panel size. */ | ||||
| if (panel->runtime_flag & PANEL_NEW_ADDED) { | if (panel->runtime_flag & PANEL_NEW_ADDED) { | ||||
| panel->runtime_flag &= ~PANEL_NEW_ADDED; | panel->runtime_flag &= ~PANEL_NEW_ADDED; | ||||
| panel->sizex = width; | panel->sizex = width; | ||||
| panel->sizey = height; | panel->sizey = height; | ||||
| } | } | ||||
| else { | else { | ||||
| const int old_sizex = panel->sizex, old_sizey = panel->sizey; | const int old_sizex = panel->sizex, old_sizey = panel->sizey; | ||||
| const int old_region_ofsx = panel->runtime.region_ofsx; | const int old_region_ofsx = panel->runtime.region_ofsx; | ||||
| /* Update width/height if non-zero. */ | /* Update width/height if non-zero. */ | ||||
| if (width != 0) { | if (width != 0) { | ||||
| panel->sizex = width; | panel->sizex = width; | ||||
| } | } | ||||
| if (height != 0 || open) { | if (height != 0 || !(panel->flag & PNL_CLOSED)) { | ||||
| panel->sizey = height; | panel->sizey = height; | ||||
| } | } | ||||
| /* Check if we need to do an animation. */ | /* Check if we need to do an animation. */ | ||||
| if (panel->sizex != old_sizex || panel->sizey != old_sizey) { | if (panel->sizex != old_sizex || panel->sizey != old_sizey) { | ||||
| panel->runtime_flag |= PANEL_ANIM_ALIGN; | panel->runtime_flag |= PANEL_ANIM_ALIGN; | ||||
| panel->ofsy += old_sizey - panel->sizey; | panel->ofsy += old_sizey - panel->sizey; | ||||
| } | } | ||||
| panel->runtime.region_ofsx = panel_region_offset_x_get(region); | panel->runtime.region_ofsx = panel_region_offset_x_get(region); | ||||
| if (old_region_ofsx != panel->runtime.region_ofsx) { | if (old_region_ofsx != panel->runtime.region_ofsx) { | ||||
| panel->runtime_flag |= PANEL_ANIM_ALIGN; | panel->runtime_flag |= PANEL_ANIM_ALIGN; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void UI_panel_end(Panel *panel, int width, int height) | |||||
| { | |||||
| /* Store the size of the buttons layout in the panel. The actual panel size | |||||
| * (including subpanels) is calculated in #UI_panels_end. */ | |||||
| panel->blocksizex = width; | |||||
| panel->blocksizey = height; | |||||
| } | |||||
| static void ui_offset_panel_block(uiBlock *block) | static void ui_offset_panel_block(uiBlock *block) | ||||
| { | { | ||||
| const uiStyle *style = UI_style_get_dpi(); | const uiStyle *style = UI_style_get_dpi(); | ||||
| /* Compute bounds and offset. */ | /* Compute bounds and offset. */ | ||||
| ui_block_bounds_calc(block); | ui_block_bounds_calc(block); | ||||
| const int ofsy = block->panel->sizey - style->panelspace; | const int ofsy = block->panel->sizey - style->panelspace; | ||||
| Show All 34 Lines | bool UI_panel_matches_search_filter(const Panel *panel) | ||||
| bool search_filter_matches = false; | bool search_filter_matches = false; | ||||
| panel_matches_search_filter_recursive(panel, &search_filter_matches); | panel_matches_search_filter_recursive(panel, &search_filter_matches); | ||||
| return search_filter_matches; | return search_filter_matches; | ||||
| } | } | ||||
| /** | /** | ||||
| * Expands a panel if it was tagged as having a result by property search, otherwise collapses it. | * Expands a panel if it was tagged as having a result by property search, otherwise collapses it. | ||||
| */ | */ | ||||
| static void panel_set_expansion_from_seach_filter_recursive(const bContext *C, Panel *panel) | static void panel_set_expansion_from_seach_filter_recursive(const bContext *C, | ||||
| Panel *panel, | |||||
| const bool use_animation) | |||||
| { | { | ||||
| if (!(panel->type->flag & PNL_NO_HEADER)) { | if (!(panel->type->flag & PNL_NO_HEADER)) { | ||||
| short start_flag = panel->flag; | short start_flag = panel->flag; | ||||
| SET_FLAG_FROM_TEST(panel->flag, !UI_panel_matches_search_filter(panel), PNL_CLOSED); | SET_FLAG_FROM_TEST(panel->flag, !UI_panel_matches_search_filter(panel), PNL_CLOSED); | ||||
| if (start_flag != panel->flag) { | if (use_animation && start_flag != panel->flag) { | ||||
| panel_activate_state(C, panel, PANEL_STATE_ANIMATION); | panel_activate_state(C, panel, PANEL_STATE_ANIMATION); | ||||
| } | } | ||||
| } | } | ||||
| /* If the panel is filtered (removed) we need to check that its children are too. */ | /* If the panel is filtered (removed) we need to check that its children are too. */ | ||||
| LISTBASE_FOREACH (Panel *, child_panel, &panel->children) { | LISTBASE_FOREACH (Panel *, child_panel, &panel->children) { | ||||
| if (child_panel->runtime_flag & PANEL_ACTIVE) { | if (child_panel->runtime_flag & PANEL_ACTIVE) { | ||||
| panel_set_expansion_from_seach_filter_recursive(C, child_panel); | panel_set_expansion_from_seach_filter_recursive(C, child_panel, use_animation); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Uses the panel's search filter flag to set its expansion, activating animation if it was closed | * Uses the panel's search filter flag to set its expansion, activating animation if it was closed | ||||
| * or opened. Note that this can't be set too often, or manual interaction becomes impossible. | * or opened. Note that this can't be set too often, or manual interaction becomes impossible. | ||||
| */ | */ | ||||
| void UI_panels_set_expansion_from_seach_filter(const bContext *C, ARegion *region) | static void region_panels_set_expansion_from_seach_filter(const bContext *C, | ||||
| ARegion *region, | |||||
| const bool use_animation) | |||||
| { | |||||
| LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { | |||||
| if (panel->runtime_flag & PANEL_ACTIVE) { | |||||
| panel_set_expansion_from_seach_filter_recursive(C, panel, use_animation); | |||||
| } | |||||
| } | |||||
| set_panels_list_data_expand_flag(C, region); | |||||
| } | |||||
| /** | |||||
| * Hide buttons in invisible layouts, which are created because in order to search, | |||||
| * buttons must be added for all panels, even panels that will end up closed. | |||||
| */ | |||||
| static void panel_remove_invisible_layouts_recursive(Panel *panel, const Panel *parent_panel) | |||||
| { | |||||
| uiBlock *block = panel->runtime.block; | |||||
| BLI_assert(block != NULL); | |||||
| BLI_assert(block->active); | |||||
| if (parent_panel != NULL && parent_panel->flag & PNL_CLOSED) { | |||||
| /* The parent panel is closed, so this panel can be completely removed. */ | |||||
| UI_block_set_search_only(block, true); | |||||
| LISTBASE_FOREACH (uiBut *, but, &block->buttons) { | |||||
| but->flag |= UI_HIDDEN; | |||||
| } | |||||
| } | |||||
| else if (panel->flag & PNL_CLOSED) { | |||||
| /* If subpanels have no search results but the parent panel does, then the parent panel open | |||||
| * and the subpanels will close. In that case there must be a way to hide the buttons in the | |||||
| * panel but keep the header buttons. */ | |||||
| LISTBASE_FOREACH (uiButtonGroup *, button_group, &block->button_groups) { | |||||
| if (button_group->flag & UI_BUTTON_GROUP_PANEL_HEADER) { | |||||
| continue; | |||||
| } | |||||
| LISTBASE_FOREACH (LinkData *, link, &button_group->buttons) { | |||||
| uiBut *but = link->data; | |||||
| but->flag |= UI_HIDDEN; | |||||
| } | |||||
| } | |||||
| } | |||||
| LISTBASE_FOREACH (Panel *, child_panel, &panel->children) { | |||||
| if (child_panel->runtime_flag & PANEL_ACTIVE) { | |||||
| BLI_assert(child_panel->runtime.block != NULL); | |||||
| panel_remove_invisible_layouts_recursive(child_panel, panel); | |||||
| } | |||||
| } | |||||
| } | |||||
| static void region_panels_remove_invisible_layouts(ARegion *region) | |||||
| { | { | ||||
| LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { | LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { | ||||
| if (panel->runtime_flag & PANEL_ACTIVE) { | if (panel->runtime_flag & PANEL_ACTIVE) { | ||||
| panel_set_expansion_from_seach_filter_recursive(C, panel); | BLI_assert(panel->runtime.block != NULL); | ||||
| panel_remove_invisible_layouts_recursive(panel, NULL); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| bool UI_panel_is_active(const Panel *panel) | bool UI_panel_is_active(const Panel *panel) | ||||
| { | { | ||||
| return panel->runtime_flag & PANEL_ACTIVE; | return panel->runtime_flag & PANEL_ACTIVE; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 1,050 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y) | void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y) | ||||
| { | { | ||||
| ScrArea *area = CTX_wm_area(C); | ScrArea *area = CTX_wm_area(C); | ||||
| region_panels_set_expansion_from_list_data(C, region); | region_panels_set_expansion_from_list_data(C, region); | ||||
| /* Update panel expansion based on property search results. */ | |||||
| if (region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) { | |||||
| /* Don't use the last update from the deactivation, or all the panels will be left closed. */ | |||||
| if (region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE) { | if (region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE) { | ||||
| UI_panels_set_expansion_from_seach_filter(C, region); | /* Update panel expansion based on property search results. Keep this inside the check | ||||
| set_panels_list_data_expand_flag(C, region); | * for an active search filter, or all panels will be left closed when a search ends. */ | ||||
| if (region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) { | |||||
| region_panels_set_expansion_from_seach_filter(C, region, true); | |||||
| } | |||||
| else if (properties_space_needs_realign(area, region)) { | |||||
| region_panels_set_expansion_from_seach_filter(C, region, false); | |||||
| } | |||||
| /* Clean up the extra panels and buttons created for searching. */ | |||||
| region_panels_remove_invisible_layouts(region); | |||||
| } | |||||
| LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { | |||||
| if (panel->runtime_flag & PANEL_ACTIVE) { | |||||
| BLI_assert(panel->runtime.block != NULL); | |||||
| panel_calculate_size_recursive(region, panel); | |||||
| } | } | ||||
| } | } | ||||
| /* Offset contents. */ | /* Offset contents. */ | ||||
| LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { | LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { | ||||
| if (block->active && block->panel) { | if (block->active && block->panel) { | ||||
| ui_offset_panel_block(block); | ui_offset_panel_block(block); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 772 Lines • Show Last 20 Lines | |||||
Noticed these checks are out-dated, so I removed them rBe839179b014a.