diff options
Diffstat (limited to 'source/blender/editors/interface/interface_panel.c')
-rw-r--r-- | source/blender/editors/interface/interface_panel.c | 398 |
1 files changed, 160 insertions, 238 deletions
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index bfe5dc223c8..aafc1c53a3b 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -85,6 +85,11 @@ typedef enum uiPanelRuntimeFlag { PANEL_USE_CLOSED_FROM_SEARCH = (1 << 8), /** The Panel was before the start of the current / latest layout pass. */ PANEL_WAS_CLOSED = (1 << 9), + /** + * Set when the panel is being dragged and while it animates back to its aligned + * position. Unlike #PANEL_STATE_ANIMATION, this is applied to sub-panels as well. + */ + PANEL_IS_DRAG_DROP = (1 << 10), } uiPanelRuntimeFlag; /* The state of the mouse position relative to the panel. */ @@ -96,8 +101,6 @@ typedef enum uiPanelMouseState { typedef enum uiHandlePanelState { PANEL_STATE_DRAG, - PANEL_STATE_DRAG_SCALE, - PANEL_STATE_WAIT_UNTAB, PANEL_STATE_ANIMATION, PANEL_STATE_EXIT, } uiHandlePanelState; @@ -110,10 +113,8 @@ typedef struct uiHandlePanelData { double starttime; /* Dragging. */ - bool is_drag_drop; int startx, starty; int startofsx, startofsy; - int startsizex, startsizey; float start_cur_xmin, start_cur_ymin; } uiHandlePanelData; @@ -209,7 +210,7 @@ static bool panel_active_animation_changed(ListBase *lb, /** * \return True if the properties editor switch tabs since the last layout pass. */ -static bool properties_space_needs_realign(ScrArea *area, ARegion *region) +static bool properties_space_needs_realign(const ScrArea *area, const ARegion *region) { if (area->spacetype == SPACE_PROPERTIES && region->regiontype == RGN_TYPE_WINDOW) { SpaceProperties *sbuts = area->spacedata.first; @@ -222,7 +223,7 @@ static bool properties_space_needs_realign(ScrArea *area, ARegion *region) return false; } -static bool panels_need_realign(ScrArea *area, ARegion *region, Panel **r_panel_animation) +static bool panels_need_realign(const ScrArea *area, ARegion *region, Panel **r_panel_animation) { *r_panel_animation = NULL; @@ -259,7 +260,7 @@ static Panel *panel_add_instanced(ARegion *region, PanelType *panel_type, PointerRNA *custom_data) { - Panel *panel = MEM_callocN(sizeof(Panel), "instanced panel"); + Panel *panel = MEM_callocN(sizeof(Panel), __func__); panel->type = panel_type; BLI_strncpy(panel->panelname, panel_type->idname, sizeof(panel->panelname)); @@ -298,7 +299,7 @@ static Panel *panel_add_instanced(ARegion *region, Panel *UI_panel_add_instanced(const bContext *C, ARegion *region, ListBase *panels, - char *panel_idname, + const char *panel_idname, PointerRNA *custom_data) { ARegionType *region_type = region->type; @@ -313,19 +314,19 @@ Panel *UI_panel_add_instanced(const bContext *C, Panel *new_panel = panel_add_instanced(region, panels, panel_type, custom_data); - /* Do this after #panel_add_instatnced so all subpanels are added. */ + /* Do this after #panel_add_instatnced so all sub-panels are added. */ panel_set_expansion_from_list_data(C, new_panel); return new_panel; } /** - * Find a unique key to append to the #PanelTyype.idname for the lookup to the panel's #uiBlock. + * Find a unique key to append to the #PanelType.idname for the lookup to the panel's #uiBlock. * Needed for instanced panels, where there can be multiple with the same type and identifier. */ void UI_list_panel_unique_str(Panel *panel, char *r_name) { - /* The panel sortorder will be unique for a specific panel type because the instanced + /* The panel sort-order will be unique for a specific panel type because the instanced * panel list is regenerated for every change in the data order / length. */ snprintf(r_name, INSTANCED_PANEL_UNIQUE_STR_LEN, "%d", panel->sortorder); } @@ -335,7 +336,7 @@ void UI_list_panel_unique_str(Panel *panel, char *r_name) * and is freed by #UI_panels_free_instanced. * * \note The only panels that should need to be deleted at runtime are panels with the - * #PNL_INSTANCED flag set. + * #PANEL_TYPE_INSTANCED flag set. */ static void panel_delete(const bContext *C, ARegion *region, ListBase *panels, Panel *panel) { @@ -362,7 +363,7 @@ void UI_panels_free_instanced(const bContext *C, ARegion *region) { /* Delete panels with the instanced flag. */ LISTBASE_FOREACH_MUTABLE (Panel *, panel, ®ion->panels) { - if ((panel->type != NULL) && (panel->type->flag & PNL_INSTANCED)) { + if ((panel->type != NULL) && (panel->type->flag & PANEL_TYPE_INSTANCED)) { /* Make sure the panel's handler is removed before deleting it. */ if (C != NULL && panel->activedata != NULL) { panel_activate_state(C, panel, PANEL_STATE_EXIT); @@ -406,7 +407,7 @@ bool UI_panel_list_matches_data(ARegion *region, int i = 0; LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { - if (panel->type != NULL && panel->type->flag & PNL_INSTANCED) { + if (panel->type != NULL && panel->type->flag & PANEL_TYPE_INSTANCED) { /* The panels were reordered by drag and drop. */ if (panel->flag & PNL_INSTANCED_LIST_ORDER_CHANGED) { return false; @@ -455,9 +456,9 @@ static void reorder_instanced_panel_list(bContext *C, ARegion *region, Panel *dr /* Find how many instanced panels with this context string. */ int list_panels_len = 0; - LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { + LISTBASE_FOREACH (const Panel *, panel, ®ion->panels) { if (panel->type) { - if (panel->type->flag & PNL_INSTANCED) { + if (panel->type->flag & PANEL_TYPE_INSTANCED) { if (panel_type_context_poll(region, panel->type, context)) { list_panels_len++; } @@ -466,11 +467,11 @@ static void reorder_instanced_panel_list(bContext *C, ARegion *region, Panel *dr } /* Sort the matching instanced panels by their display order. */ - PanelSort *panel_sort = MEM_callocN(list_panels_len * sizeof(*panel_sort), "instancedpanelsort"); + PanelSort *panel_sort = MEM_callocN(list_panels_len * sizeof(*panel_sort), __func__); PanelSort *sort_index = panel_sort; LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { if (panel->type) { - if (panel->type->flag & PNL_INSTANCED) { + if (panel->type->flag & PANEL_TYPE_INSTANCED) { if (panel_type_context_poll(region, panel->type, context)) { sort_index->panel = panel; sort_index++; @@ -523,7 +524,7 @@ static bool panel_set_expand_from_list_data_recursive(Panel *panel, short flag, static void panel_set_expansion_from_list_data(const bContext *C, Panel *panel) { BLI_assert(panel->type != NULL); - BLI_assert(panel->type->flag & PNL_INSTANCED); + BLI_assert(panel->type->flag & PANEL_TYPE_INSTANCED); if (panel->type->get_list_data_expand_flag == NULL) { /* Instanced panel doesn't support loading expansion. */ return; @@ -546,7 +547,7 @@ static void region_panels_set_expansion_from_list_data(const bContext *C, ARegio LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { if (panel->runtime_flag & PANEL_ACTIVE) { PanelType *panel_type = panel->type; - if (panel_type != NULL && panel->type->flag & PNL_INSTANCED) { + if (panel_type != NULL && panel->type->flag & PANEL_TYPE_INSTANCED) { panel_set_expansion_from_list_data(C, panel); } } @@ -556,12 +557,12 @@ static void region_panels_set_expansion_from_list_data(const bContext *C, ARegio /** * Recursive implementation for #set_panels_list_data_expand_flag. */ -static void get_panel_expand_flag(Panel *panel, short *flag, short *flag_index) +static void get_panel_expand_flag(const Panel *panel, short *flag, short *flag_index) { const bool open = !(panel->flag & PNL_CLOSED); SET_FLAG_FROM_TEST(*flag, open, (1 << *flag_index)); - LISTBASE_FOREACH (Panel *, child, &panel->children) { + LISTBASE_FOREACH (const Panel *, child, &panel->children) { *flag_index = *flag_index + 1; get_panel_expand_flag(child, flag, flag_index); } @@ -571,8 +572,8 @@ static void get_panel_expand_flag(Panel *panel, short *flag, short *flag_index) * Call the callback to store the panel and sub-panel expansion settings in the list item that * corresponds to each instanced panel. * - * \note This needs to iterate through all of the regions panels because the panel with changed - * expansion could have been the sub-panel of a instanced panel, meaning it might not know + * \note This needs to iterate through all of the region's panels because the panel with changed + * expansion might have been the sub-panel of an instanced panel, meaning it might not know * which list item it corresponds to. */ static void set_panels_list_data_expand_flag(const bContext *C, const ARegion *region) @@ -584,7 +585,7 @@ static void set_panels_list_data_expand_flag(const bContext *C, const ARegion *r } /* Check for #PANEL_ACTIVE so we only set the expand flag for active panels. */ - if (panel_type->flag & PNL_INSTANCED && panel->runtime_flag & PANEL_ACTIVE) { + if (panel_type->flag & PANEL_TYPE_INSTANCED && panel->runtime_flag & PANEL_ACTIVE) { short expand_flag; short flag_index = 0; get_panel_expand_flag(panel, &expand_flag, &flag_index); @@ -603,22 +604,26 @@ static void set_panels_list_data_expand_flag(const bContext *C, const ARegion *r /** * Set flag state for a panel and its sub-panels. - * - * \return True if this function changed any of the flags, false if it didn't. */ -static bool panel_set_flag_recursive(Panel *panel, int flag, bool value) +static void panel_set_flag_recursive(Panel *panel, short flag, bool value) { - const short flag_original = panel->flag; - SET_FLAG_FROM_TEST(panel->flag, value, flag); - bool changed = (flag_original != panel->flag); - LISTBASE_FOREACH (Panel *, child, &panel->children) { - changed |= panel_set_flag_recursive(child, flag, value); + panel_set_flag_recursive(child, flag, value); } +} - return changed; +/** + * Set runtime flag state for a panel and its sub-panels. + */ +static void panel_set_runtime_flag_recursive(Panel *panel, short flag, bool value) +{ + SET_FLAG_FROM_TEST(panel->runtime_flag, value, flag); + + LISTBASE_FOREACH (Panel *, sub_panel, &panel->children) { + panel_set_runtime_flag_recursive(sub_panel, flag, value); + } } static void panels_collapse_all(ARegion *region, const Panel *from_panel) @@ -631,7 +636,7 @@ static void panels_collapse_all(ARegion *region, const Panel *from_panel) PanelType *pt = panel->type; /* Close panels with headers in the same context. */ - if (pt && from_pt && !(pt->flag & PNL_NO_HEADER)) { + if (pt && from_pt && !(pt->flag & PANEL_TYPE_NO_HEADER)) { if (!pt->context[0] || !from_pt->context[0] || STREQ(pt->context, from_pt->context)) { if ((panel->flag & PNL_PIN) || !category || !pt->category[0] || STREQ(pt->category, category)) { @@ -657,7 +662,7 @@ static bool panel_type_context_poll(ARegion *region, return false; } -Panel *UI_panel_find_by_type(ListBase *lb, PanelType *pt) +Panel *UI_panel_find_by_type(ListBase *lb, const PanelType *pt) { const char *idname = pt->idname; @@ -681,11 +686,11 @@ Panel *UI_panel_begin( const bool newpanel = (panel == NULL); if (newpanel) { - panel = MEM_callocN(sizeof(Panel), "new panel"); + panel = MEM_callocN(sizeof(Panel), __func__); panel->type = pt; BLI_strncpy(panel->panelname, idname, sizeof(panel->panelname)); - if (pt->flag & PNL_DEFAULT_CLOSED) { + if (pt->flag & PANEL_TYPE_DEFAULT_CLOSED) { panel->flag |= PNL_CLOSED; panel->runtime_flag |= PANEL_WAS_CLOSED; } @@ -753,8 +758,8 @@ Panel *UI_panel_begin( /** * 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. + * panel headers for the panel search process that happens later. This Should be + * called before adding buttons for the panel's header layout. */ void UI_panel_header_buttons_begin(Panel *panel) { @@ -764,20 +769,20 @@ void UI_panel_header_buttons_begin(Panel *panel) } /** - * Allow new button groups to be created after the header group. + * Finish the button group for the panel header to avoid putting panel body buttons in it. */ 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. */ + /* A button group should always be created in #UI_panel_header_buttons_begin. */ BLI_assert(!BLI_listbase_is_empty(&block->button_groups)); uiButtonGroup *button_group = block->button_groups.last; button_group->flag &= ~UI_BUTTON_GROUP_LOCK; - /* Repurpose the first "header" button group if it is empty, in case the first button added to + /* 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_is_single(&block->button_groups) && @@ -785,9 +790,9 @@ void UI_panel_header_buttons_end(Panel *panel) button_group->flag &= ~UI_BUTTON_GROUP_PANEL_HEADER; } else { - /* We should still always add a new button group. Although this results in many empty groups, - * without it, new buttons not protected with a #ui_block_new_button_group call would end up - * in the panel header group. */ + /* Always add a new button group. Although this may result in many empty groups, without it, + * new buttons in the panel body not protected with a #ui_block_new_button_group call would + * end up in the panel header group. */ ui_block_new_button_group(block, 0); } } @@ -805,7 +810,7 @@ static float panel_region_offset_x_get(const ARegion *region) /** * Starting from the "block size" set in #UI_panel_end, calculate the full size - * of the panel including the subpanel headers and buttons. + * of the panel including the sub-panel headers and buttons. */ static void panel_calculate_size_recursive(ARegion *region, Panel *panel) { @@ -854,7 +859,7 @@ static void panel_calculate_size_recursive(ARegion *region, Panel *panel) 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. */ + * (including sub-panels) is calculated in #UI_panels_end. */ panel->blocksizex = width; panel->blocksizey = height; } @@ -878,7 +883,7 @@ static void ui_offset_panel_block(uiBlock *block) block->rect.xmin = block->rect.ymin = 0.0; } -void ui_panel_tag_search_filter_match(struct Panel *panel) +void ui_panel_tag_search_filter_match(Panel *panel) { panel->runtime_flag |= PANEL_SEARCH_FILTER_MATCH; } @@ -907,25 +912,22 @@ bool UI_panel_matches_search_filter(const Panel *panel) } /** - * Set the flag telling the panel to use its search result status for - * its expansion. Also activate animation if that changes the expansion. + * Set the flag telling the panel to use its search result status for its expansion. */ static void panel_set_expansion_from_seach_filter_recursive(const bContext *C, Panel *panel, - const bool use_search_closed, - const bool use_animation) + const bool use_search_closed) { /* This has to run on inactive panels that may not have a type, - * but we can prevent running on headerless panels in some cases. */ - if (panel->type == NULL || !(panel->type->flag & PNL_NO_HEADER)) { + * but we can prevent running on header-less panels in some cases. */ + if (panel->type == NULL || !(panel->type->flag & PANEL_TYPE_NO_HEADER)) { SET_FLAG_FROM_TEST(panel->runtime_flag, use_search_closed, PANEL_USE_CLOSED_FROM_SEARCH); } LISTBASE_FOREACH (Panel *, child_panel, &panel->children) { - /* Don't check if the subpanel is active, otherwise the + /* Don't check if the sub-panel is active, otherwise the * expansion won't be reset when the parent is closed. */ - panel_set_expansion_from_seach_filter_recursive( - C, child_panel, use_search_closed, use_animation); + panel_set_expansion_from_seach_filter_recursive(C, child_panel, use_search_closed); } } @@ -934,18 +936,19 @@ static void panel_set_expansion_from_seach_filter_recursive(const bContext *C, */ static void region_panels_set_expansion_from_seach_filter(const bContext *C, ARegion *region, - const bool use_search_closed, - const bool use_animation) + const bool use_search_closed) { LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { - panel_set_expansion_from_seach_filter_recursive(C, panel, use_search_closed, use_animation); + /* Don't check if the panel is active, otherwise the expansion won't + * be correct when switching back to tab after exiting search. */ + panel_set_expansion_from_seach_filter_recursive(C, panel, use_search_closed); } 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. + * Hide buttons in invisible layouts, which are created because buttons must be + * added for all panels in order to search, even panels that will end up closed. */ static void panel_remove_invisible_layouts_recursive(Panel *panel, const Panel *parent_panel) { @@ -960,8 +963,8 @@ static void panel_remove_invisible_layouts_recursive(Panel *panel, const Panel * } } else if (UI_panel_is_closed(panel)) { - /* 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 + /* If sub-panels have no search results but the parent panel does, then the parent panel open + * and the sub-panels 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) { @@ -999,7 +1002,7 @@ static void region_panels_remove_invisible_layouts(ARegion *region) bool UI_panel_is_closed(const Panel *panel) { /* Header-less panels can never be closed, otherwise they could disappear. */ - if (panel->type && panel->type->flag & PNL_NO_HEADER) { + if (panel->type && panel->type->flag & PANEL_TYPE_NO_HEADER) { return false; } @@ -1029,42 +1032,24 @@ void UI_panels_draw(const bContext *C, ARegion *region) /* Draw in reverse order, because #uiBlocks are added in reverse order * and we need child panels to draw on top. */ LISTBASE_FOREACH_BACKWARD (uiBlock *, block, ®ion->uiblocks) { - if (block->active && block->panel && !(block->panel->flag & PNL_SELECT) && + if (block->active && block->panel && !UI_panel_is_dragging(block->panel) && !UI_block_is_search_only(block)) { UI_block_draw(C, block); } } LISTBASE_FOREACH_BACKWARD (uiBlock *, block, ®ion->uiblocks) { - if (block->active && block->panel && (block->panel->flag & PNL_SELECT) && + if (block->active && block->panel && UI_panel_is_dragging(block->panel) && !UI_block_is_search_only(block)) { UI_block_draw(C, block); } } } -/* Triangle 'icon' for panel header. */ -void UI_draw_icon_tri(float x, float y, char dir, const float color[4]) -{ - const float f3 = 0.05 * U.widget_unit; - const float f5 = 0.15 * U.widget_unit; - const float f7 = 0.25 * U.widget_unit; - - if (dir == 'h') { - UI_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y, color); - } - else if (dir == 't') { - UI_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3, color); - } - else { /* 'v' = vertical, down. */ - UI_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7, color); - } -} - #define PNL_ICON UI_UNIT_X /* Could be UI_UNIT_Y too. */ /* For button layout next to label. */ -void UI_panel_label_offset(uiBlock *block, int *r_x, int *r_y) +void UI_panel_label_offset(const uiBlock *block, int *r_x, int *r_y) { Panel *panel = block->panel; const bool is_subpanel = (panel->type && panel->type->parent); @@ -1125,7 +1110,7 @@ void ui_draw_aligned_panel(const uiStyle *style, * can't be dragged. This may be changed in future. */ show_background); const int panel_col = is_subpanel ? TH_PANEL_SUB_BACK : TH_PANEL_BACK; - const bool draw_box_style = (panel->type && panel->type->flag & PNL_DRAW_BOX); + const bool draw_box_style = (panel->type && panel->type->flag & PANEL_TYPE_DRAW_BOX); /* Use the theme for box widgets for box-style panels. */ uiWidgetColors *box_wcol = NULL; @@ -1137,7 +1122,7 @@ void ui_draw_aligned_panel(const uiStyle *style, const uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - if (panel->type && (panel->type->flag & PNL_NO_HEADER)) { + if (panel->type && (panel->type->flag & PANEL_TYPE_NO_HEADER)) { if (show_background) { immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); immUniformThemeColor(panel_col); @@ -1593,7 +1578,7 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) static int get_panel_size_y(const Panel *panel) { - if (panel->type && (panel->type->flag & PNL_NO_HEADER)) { + if (panel->type && (panel->type->flag & PANEL_TYPE_NO_HEADER)) { return panel->sizey; } @@ -1604,7 +1589,7 @@ static int get_panel_real_size_y(const Panel *panel) { const int sizey = UI_panel_is_closed(panel) ? 0 : panel->sizey; - if (panel->type && (panel->type->flag & PNL_NO_HEADER)) { + if (panel->type && (panel->type->flag & PANEL_TYPE_NO_HEADER)) { return sizey; } @@ -1628,14 +1613,9 @@ static int get_panel_real_ofsy(Panel *panel) return panel->ofsy; } -bool UI_panel_is_dragging(const struct Panel *panel) +bool UI_panel_is_dragging(const Panel *panel) { - uiHandlePanelData *data = panel->activedata; - if (!data) { - return false; - } - - return data->is_drag_drop; + return panel->runtime_flag & PANEL_IS_DRAG_DROP; } /** @@ -1653,13 +1633,13 @@ static int find_highest_panel(const void *a, const void *b) /* Stick uppermost header-less panels to the top of the region - * prevent them from being sorted (multiple header-less panels have to be sorted though). */ - if (panel_a->type->flag & PNL_NO_HEADER && panel_b->type->flag & PNL_NO_HEADER) { + if (panel_a->type->flag & PANEL_TYPE_NO_HEADER && panel_b->type->flag & PANEL_TYPE_NO_HEADER) { /* Skip and check for `ofsy` and #Panel.sortorder below. */ } - if (panel_a->type->flag & PNL_NO_HEADER) { + if (panel_a->type->flag & PANEL_TYPE_NO_HEADER) { return -1; } - if (panel_b->type->flag & PNL_NO_HEADER) { + if (panel_b->type->flag & PANEL_TYPE_NO_HEADER) { return 1; } @@ -1758,7 +1738,7 @@ static bool uiAlignPanelStep(ARegion *region, const float factor, const bool dra const int region_offset_x = panel_region_offset_x_get(region); for (int i = 0; i < active_panels_len; i++) { PanelSort *ps = &panel_sort[i]; - const bool use_box = ps->panel->type->flag & PNL_DRAW_BOX; + const bool use_box = ps->panel->type->flag & PANEL_TYPE_DRAW_BOX; ps->panel->runtime.region_ofsx = region_offset_x; ps->new_offset_x = region_offset_x + ((use_box) ? UI_PANEL_BOX_STYLE_MARGIN : 0); } @@ -1768,7 +1748,7 @@ static bool uiAlignPanelStep(ARegion *region, const float factor, const bool dra PanelSort *ps = &panel_sort[i]; y -= get_panel_real_size_y(ps->panel); - const bool use_box = ps->panel->type->flag & PNL_DRAW_BOX; + const bool use_box = ps->panel->type->flag & PANEL_TYPE_DRAW_BOX; if (use_box) { y -= UI_PANEL_BOX_STYLE_MARGIN; } @@ -1848,25 +1828,17 @@ static void ui_do_animate(bContext *C, Panel *panel) float fac = (PIL_check_seconds_timer() - data->starttime) / ANIMATION_TIME; fac = min_ff(sqrtf(fac), 1.0f); - /* For max 1 second, interpolate positions. */ if (uiAlignPanelStep(region, fac, false)) { ED_region_tag_redraw(region); } else { - fac = 1.0f; - } - - if (fac >= 1.0f) { - /* Store before data is freed. */ - const bool is_drag_drop = data->is_drag_drop; - - panel_activate_state(C, panel, PANEL_STATE_EXIT); - if (is_drag_drop) { - /* Note: doing this in #panel_activate_state would require removing `const` for context in - * many other places. */ + if (UI_panel_is_dragging(panel)) { + /* Note: doing this in #panel_activate_state would require + * removing `const` for context in many other places. */ reorder_instanced_panel_list(C, region, panel); } - return; + + panel_activate_state(C, panel, PANEL_STATE_EXIT); } } @@ -1874,7 +1846,7 @@ static void panels_layout_begin_clear_flags(ListBase *lb) { LISTBASE_FOREACH (Panel *, panel, lb) { /* Flags to copy over to the next layout pass. */ - const short flag_copy = PANEL_USE_CLOSED_FROM_SEARCH; + const short flag_copy = PANEL_USE_CLOSED_FROM_SEARCH | PANEL_IS_DRAG_DROP; const bool was_active = panel->runtime_flag & PANEL_ACTIVE; const bool was_closed = UI_panel_is_closed(panel); @@ -1902,10 +1874,10 @@ void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y) const bool region_search_filter_active = region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE; if (properties_space_needs_realign(area, region)) { - region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active, false); + region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active); } else if (region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) { - region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active, true); + region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active); } if (region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE) { @@ -1955,38 +1927,19 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel) ARegion *region = CTX_wm_region(C); /* Keep the drag position in the region with a small pad to keep the panel visible. */ - const int x = clamp_i(event->x, region->winrct.xmin, region->winrct.xmax + DRAG_REGION_PAD); const int y = clamp_i(event->y, region->winrct.ymin, region->winrct.ymax + DRAG_REGION_PAD); - float dx = (float)(x - data->startx); float dy = (float)(y - data->starty); /* Adjust for region zoom. */ - dx *= BLI_rctf_size_x(®ion->v2d.cur) / (float)BLI_rcti_size_x(®ion->winrct); dy *= BLI_rctf_size_y(®ion->v2d.cur) / (float)BLI_rcti_size_y(®ion->winrct); - if (data->state == PANEL_STATE_DRAG_SCALE) { - panel->sizex = MAX2(data->startsizex + dx, UI_PANEL_MINX); - - if (data->startsizey - dy < UI_PANEL_MINY) { - dy = -UI_PANEL_MINY + data->startsizey; - } - - panel->sizey = data->startsizey - dy; - panel->ofsy = data->startofsy + dy; - } - else { - /* Reset the panel snapping, to allow dragging away from snapped edges. */ - panel->snap = PNL_SNAP_NONE; + /* Add the movement of the view due to edge scrolling while dragging. */ + dy += ((float)region->v2d.cur.ymin - data->start_cur_ymin); - /* Add the movement of the view due to edge scrolling while dragging. */ - dx += ((float)region->v2d.cur.xmin - data->start_cur_xmin); - dy += ((float)region->v2d.cur.ymin - data->start_cur_ymin); - panel->ofsx = data->startofsx + round_fl_to_int(dx); - panel->ofsy = data->startofsy + round_fl_to_int(dy); + panel->ofsy = data->startofsy + round_fl_to_int(dy); - uiAlignPanelStep(region, 0.2f, true); - } + uiAlignPanelStep(region, 0.2f, true); ED_region_tag_redraw(region); } @@ -2042,7 +1995,7 @@ static void ui_panel_drag_collapse(const bContext *C, float xy_b_block[2] = {UNPACK2(xy_dst)}; Panel *panel = block->panel; - if (panel == NULL || (panel->type && (panel->type->flag & PNL_NO_HEADER))) { + if (panel == NULL || (panel->type && (panel->type->flag & PANEL_TYPE_NO_HEADER))) { continue; } const int oldflag = panel->flag; @@ -2135,9 +2088,9 @@ static void ui_panel_drag_collapse_handler_add(const bContext *C, const bool was * \param mx: The mouse x coordinate, in panel space. */ static void ui_handle_panel_header(const bContext *C, - uiBlock *block, + const uiBlock *block, const int mx, - short int event_type, + const int event_type, const short ctrl, const short shift) { @@ -2145,7 +2098,7 @@ static void ui_handle_panel_header(const bContext *C, ARegion *region = CTX_wm_region(C); BLI_assert(panel->type != NULL); - BLI_assert(!(panel->type->flag & PNL_NO_HEADER)); + BLI_assert(!(panel->type->flag & PANEL_TYPE_NO_HEADER)); const bool is_subpanel = (panel->type->parent != NULL); const bool use_pin = UI_panel_category_is_visible(region) && !is_subpanel; @@ -2187,27 +2140,10 @@ static void ui_handle_panel_header(const bContext *C, } } - if (UI_panel_is_closed(panel)) { - panel->flag &= ~PNL_CLOSED; - /* Snap back up so full panel aligns with screen edge. */ - if (panel->snap & PNL_SNAP_BOTTOM) { - panel->ofsy = 0; - } + SET_FLAG_FROM_TEST(panel->flag, !UI_panel_is_closed(panel), PNL_CLOSED); - if (event_type == LEFTMOUSE) { - ui_panel_drag_collapse_handler_add(C, false); - } - } - else { - /* Snap down to bottom screen edge. */ - panel->flag |= PNL_CLOSED; - if (panel->snap & PNL_SNAP_BOTTOM) { - panel->ofsy = -panel->sizey; - } - - if (event_type == LEFTMOUSE) { - ui_panel_drag_collapse_handler_add(C, true); - } + if (event_type == LEFTMOUSE) { + ui_panel_drag_collapse_handler_add(C, UI_panel_is_closed(panel)); } set_panels_list_data_expand_flag(C, region); @@ -2244,7 +2180,7 @@ bool UI_panel_category_is_visible(const ARegion *region) region->panels_category.first != region->panels_category.last; } -PanelCategoryDyn *UI_panel_category_find(ARegion *region, const char *idname) +PanelCategoryDyn *UI_panel_category_find(const ARegion *region, const char *idname) { return BLI_findstring(®ion->panels_category, idname, offsetof(PanelCategoryDyn, idname)); } @@ -2325,10 +2261,10 @@ const char *UI_panel_category_active_get(ARegion *region, bool set_fallback) return NULL; } -PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(ARegion *region, const int x, const int y) +static PanelCategoryDyn *panel_categories_find_mouse_over(ARegion *region, const wmEvent *event) { LISTBASE_FOREACH (PanelCategoryDyn *, ptd, ®ion->panels_category) { - if (BLI_rcti_isect_pt(&ptd->rect, x, y)) { + if (BLI_rcti_isect_pt(&ptd->rect, event->mval[0], event->mval[1])) { return ptd; } } @@ -2336,11 +2272,6 @@ PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(ARegion *region, const in return NULL; } -PanelCategoryDyn *UI_panel_category_find_mouse_over(ARegion *region, const wmEvent *event) -{ - return UI_panel_category_find_mouse_over_ex(region, event->mval[0], event->mval[1]); -} - void UI_panel_category_add(ARegion *region, const char *name) { PanelCategoryDyn *pc_dyn = MEM_callocN(sizeof(*pc_dyn), __func__); @@ -2436,7 +2367,7 @@ int ui_handler_panel_region(bContext *C, /* Handle category tabs. */ if (UI_panel_category_is_visible(region)) { if (event->type == LEFTMOUSE) { - PanelCategoryDyn *pc_dyn = UI_panel_category_find_mouse_over(region, event); + PanelCategoryDyn *pc_dyn = panel_categories_find_mouse_over(region, event); if (pc_dyn) { UI_panel_category_active_set(region, pc_dyn->idname); ED_region_tag_redraw(region); @@ -2466,7 +2397,7 @@ int ui_handler_panel_region(bContext *C, continue; } /* We can't expand or collapse panels without headers, they would disappear. */ - if (panel->type->flag & PNL_NO_HEADER) { + if (panel->type->flag & PANEL_TYPE_NO_HEADER) { continue; } @@ -2617,89 +2548,80 @@ static void ui_handler_remove_panel(bContext *C, void *userdata) panel_activate_state(C, panel, PANEL_STATE_EXIT); } -static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelState state) +static void panel_handle_data_ensure(const bContext *C, + wmWindow *win, + const ARegion *region, + Panel *panel, + const uiHandlePanelState state) +{ + if (panel->activedata == NULL) { + panel->activedata = MEM_callocN(sizeof(uiHandlePanelData), __func__); + WM_event_add_ui_handler( + C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, panel, 0); + } + + uiHandlePanelData *data = panel->activedata; + + data->animtimer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, ANIMATION_INTERVAL); + + data->state = state; + data->startx = win->eventstate->x; + data->starty = win->eventstate->y; + data->startofsx = panel->ofsx; + data->startofsy = panel->ofsy; + data->start_cur_xmin = region->v2d.cur.xmin; + data->start_cur_ymin = region->v2d.cur.ymin; + data->starttime = PIL_check_seconds_timer(); +} + +/** + * \note "select" and "drag drop" flags: First, the panel is "picked up" and both flags are set. + * Then when the mouse releases and the panel starts animating to its aligned position, PNL_SELECT + * is unset. When the animation finishes, PANEL_IS_DRAG_DROP is cleared. + */ +static void panel_activate_state(const bContext *C, Panel *panel, const uiHandlePanelState state) { uiHandlePanelData *data = panel->activedata; wmWindow *win = CTX_wm_window(C); ARegion *region = CTX_wm_region(C); - if (data && data->state == state) { + if (data != NULL && data->state == state) { return; } - const bool was_drag_drop = (data && data->state == PANEL_STATE_DRAG); - - /* Set selection state for the panel and its sub-panels, which need to know they are selected - * too so they can be drawn above their parent when it's dragged. */ - if (state == PANEL_STATE_EXIT || state == PANEL_STATE_ANIMATION) { - panel_set_flag_recursive(panel, PNL_SELECT, false); - } - else { + if (state == PANEL_STATE_DRAG) { panel_set_flag_recursive(panel, PNL_SELECT, true); - } + panel_set_runtime_flag_recursive(panel, PANEL_IS_DRAG_DROP, true); - if (data && data->animtimer) { - WM_event_remove_timer(CTX_wm_manager(C), win, data->animtimer); - data->animtimer = NULL; - } + panel_handle_data_ensure(C, win, region, panel, state); - if (state == PANEL_STATE_EXIT) { - MEM_freeN(data); - panel->activedata = NULL; - - WM_event_remove_ui_handler( - &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, panel, false); + /* Initiate edge panning during drags for scrolling beyond the initial region view. */ + wmOperatorType *ot = WM_operatortype_find("VIEW2D_OT_edge_pan", true); + ui_handle_afterfunc_add_operator(ot, WM_OP_INVOKE_DEFAULT, true); } - else { - if (!data) { - data = MEM_callocN(sizeof(uiHandlePanelData), "uiHandlePanelData"); - panel->activedata = data; + else if (state == PANEL_STATE_ANIMATION) { + panel_set_flag_recursive(panel, PNL_SELECT, false); - WM_event_add_ui_handler( - C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, panel, 0); - } + panel_handle_data_ensure(C, win, region, panel, state); + } + else if (state == PANEL_STATE_EXIT) { + panel_set_runtime_flag_recursive(panel, PANEL_IS_DRAG_DROP, false); - if (ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG)) { - data->animtimer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, ANIMATION_INTERVAL); - } + BLI_assert(data != NULL); - /* Initiate edge panning during drags so we can move beyond the initial region view. */ - if (state == PANEL_STATE_DRAG) { - wmOperatorType *ot = WM_operatortype_find("VIEW2D_OT_edge_pan", true); - ui_handle_afterfunc_add_operator(ot, WM_OP_INVOKE_DEFAULT, true); + if (data->animtimer) { + WM_event_remove_timer(CTX_wm_manager(C), win, data->animtimer); + data->animtimer = NULL; } - data->state = state; - data->startx = win->eventstate->x; - data->starty = win->eventstate->y; - data->startofsx = panel->ofsx; - data->startofsy = panel->ofsy; - data->startsizex = panel->sizex; - data->startsizey = panel->sizey; - data->start_cur_xmin = region->v2d.cur.xmin; - data->start_cur_ymin = region->v2d.cur.ymin; - data->starttime = PIL_check_seconds_timer(); + MEM_freeN(data); + panel->activedata = NULL; - /* Remember drag drop state even when animating to the aligned position after dragging. */ - data->is_drag_drop = was_drag_drop; - if (state == PANEL_STATE_DRAG) { - data->is_drag_drop = true; - } + WM_event_remove_ui_handler( + &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, panel, false); } ED_region_tag_redraw(region); } -PanelType *UI_paneltype_find(int space_id, int region_id, const char *idname) -{ - SpaceType *st = BKE_spacetype_from_id(space_id); - if (st) { - ARegionType *art = BKE_regiontype_from_id(st, region_id); - if (art) { - return BLI_findstring(&art->paneltypes, idname, offsetof(PanelType, idname)); - } - } - return NULL; -} - /** \} */ |