diff --git a/source/blender/editors/screen/screen_draw.cc b/source/blender/editors/screen/screen_draw.cc index 5ffb7ab32af..31b917483d5 100644 --- a/source/blender/editors/screen/screen_draw.cc +++ b/source/blender/editors/screen/screen_draw.cc @@ -22,6 +22,7 @@ #include "BLI_listbase.h" #include "BLI_math_vector.h" #include "BLI_rect.h" +#include "BLI_time.h" #include "BLT_translation.hh" @@ -667,3 +668,81 @@ void screen_draw_split_preview(ScrArea *area, const eScreenAxis dir_axis, const } UI_draw_roundbox_4fv(&rect, true, 0.0f, border); } + +struct AreaAnimateHighlightData { + wmWindow *win; + bScreen *screen; + rctf rect; + float inner[4]; + float outline[4]; + double start_time; + double end_time; + void *draw_callback; +}; + +static void area_animate_highlight_cb(const wmWindow * /*win*/, void *userdata) +{ + const AreaAnimateHighlightData *data = static_cast(userdata); + + double now = BLI_time_now_seconds(); + if (now > data->end_time) { + WM_draw_cb_exit(data->win, data->draw_callback); + MEM_freeN(const_cast(data)); + data = nullptr; + return; + } + + const float factor = pow((now - data->start_time) / (data->end_time - data->start_time), 2); + const bool do_inner = data->inner[3] > 0.0f; + const bool do_outline = data->outline[3] > 0.0f; + + float inner_color[4]; + if (do_inner) { + inner_color[0] = data->inner[0]; + inner_color[1] = data->inner[1]; + inner_color[2] = data->inner[2]; + inner_color[3] = (1.0f - factor) * data->inner[3]; + } + + float outline_color[4]; + if (do_outline) { + outline_color[0] = data->outline[0]; + outline_color[1] = data->outline[1]; + outline_color[2] = data->outline[2]; + outline_color[3] = (1.0f - factor) * data->outline[3]; + } + + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_4fv_ex(&data->rect, + do_inner ? inner_color : nullptr, + nullptr, + 1.0f, + do_outline ? outline_color : nullptr, + U.pixelsize, + EDITORRADIUS); + + data->screen->do_refresh = true; +} + +void screen_animate_area_highlight(wmWindow *win, + bScreen *screen, + const rcti *rect, + float inner[4], + float outline[4], + float seconds) +{ + AreaAnimateHighlightData *data = MEM_callocN( + "screen_animate_area_highlight"); + data->win = win; + data->screen = screen; + BLI_rctf_rcti_copy(&data->rect, rect); + if (inner) { + copy_v4_v4(data->inner, inner); + } + if (outline) { + copy_v4_v4(data->outline, outline); + } + data->start_time = BLI_time_now_seconds(); + data->end_time = data->start_time + seconds; + data->draw_callback = WM_draw_cb_activate(win, area_animate_highlight_cb, data); +} diff --git a/source/blender/editors/screen/screen_edit.cc b/source/blender/editors/screen/screen_edit.cc index e5d2d6a872b..eadd34579c6 100644 --- a/source/blender/editors/screen/screen_edit.cc +++ b/source/blender/editors/screen/screen_edit.cc @@ -564,7 +564,18 @@ static bool screen_area_join_ex(bContext *C, if (close_all_remainders || offset1 < 0 || offset2 > 0) { /* Close both if trimming `sa1`. */ + float inner[4] = {0.0f, 0.0f, 0.0f, 0.7f}; + if (side1) { + rcti rect = {side1->v1->vec.x, side1->v3->vec.x, side1->v1->vec.y, side1->v3->vec.y}; + screen_animate_area_highlight( + CTX_wm_window(C), CTX_wm_screen(C), &rect, inner, nullptr, AREA_CLOSE_FADEOUT); + } screen_area_close(C, reports, screen, side1); + if (side2) { + rcti rect = {side2->v1->vec.x, side2->v3->vec.x, side2->v1->vec.y, side2->v3->vec.y}; + screen_animate_area_highlight( + CTX_wm_window(C), CTX_wm_screen(C), &rect, inner, nullptr, AREA_CLOSE_FADEOUT); + } screen_area_close(C, reports, screen, side2); } else { diff --git a/source/blender/editors/screen/screen_intern.hh b/source/blender/editors/screen/screen_intern.hh index 80fedac9cef..44d6db28e50 100644 --- a/source/blender/editors/screen/screen_intern.hh +++ b/source/blender/editors/screen/screen_intern.hh @@ -80,6 +80,11 @@ enum class AreaDockTarget { /* Less expansion needed for global edges. */ #define BORDERPADDING_GLOBAL (3.0f * UI_SCALE_FAC) +#define AREA_CLOSE_FADEOUT 0.22f /* seconds */ +#define AREA_DOCK_FADEOUT 0.20f /* seconds */ +#define AREA_JOIN_FADEOUT 0.15f /* seconds */ +#define AREA_SPLIT_FADEOUT 0.15f /* seconds */ + /* `area.cc` */ /** @@ -112,6 +117,13 @@ void screen_draw_move_highlight(const wmWindow *win, bScreen *screen, eScreenAxi void screen_draw_region_scale_highlight(ARegion *region); +void screen_animate_area_highlight(wmWindow *win, + bScreen *screen, + const rcti *rect, + float inner[4], + float outline[4], + float seconds); + /* `screen_edit.cc` */ /** diff --git a/source/blender/editors/screen/screen_ops.cc b/source/blender/editors/screen/screen_ops.cc index b4afff03054..efab96724c1 100644 --- a/source/blender/editors/screen/screen_ops.cc +++ b/source/blender/editors/screen/screen_ops.cc @@ -1583,6 +1583,10 @@ static wmOperatorStatus area_close_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + float inner[4] = {0.0f, 0.0f, 0.0f, 0.7f}; + screen_animate_area_highlight( + CTX_wm_window(C), CTX_wm_screen(C), &area->totrct, inner, nullptr, AREA_CLOSE_FADEOUT); + if (!screen_area_close(C, op->reports, screen, area)) { BKE_report(op->reports, RPT_ERROR, "Unable to close area"); return OPERATOR_CANCELLED; @@ -2597,6 +2601,14 @@ static wmOperatorStatus area_split_modal(bContext *C, wmOperator *op, const wmEv case LEFTMOUSE: if (sd->previewmode) { + float inner[4] = {1.0f, 1.0f, 1.0f, 0.1f}; + float outline[4] = {1.0f, 1.0f, 1.0f, 0.3f}; + screen_animate_area_highlight(CTX_wm_window(C), + CTX_wm_screen(C), + &sd->sarea->totrct, + inner, + outline, + AREA_SPLIT_FADEOUT); area_split_apply(C, op); area_split_exit(C, op); return OPERATOR_FINISHED; @@ -3819,6 +3831,22 @@ static bool area_join_apply(bContext *C, wmOperator *op) bScreen *screen = CTX_wm_screen(C); + /* Rect of the combined areas. */ + const bool vertical = SCREEN_DIR_IS_VERTICAL(jd->dir); + rcti combined{}; + combined.xmin = vertical ? std::max(jd->sa1->totrct.xmin, jd->sa2->totrct.xmin) : + std::min(jd->sa1->totrct.xmin, jd->sa2->totrct.xmin); + combined.xmax = vertical ? std::min(jd->sa1->totrct.xmax, jd->sa2->totrct.xmax) : + std::max(jd->sa1->totrct.xmax, jd->sa2->totrct.xmax); + combined.ymin = vertical ? std::min(jd->sa1->totrct.ymin, jd->sa2->totrct.ymin) : + std::max(jd->sa1->totrct.ymin, jd->sa2->totrct.ymin); + combined.ymax = vertical ? std::max(jd->sa1->totrct.ymax, jd->sa2->totrct.ymax) : + std::min(jd->sa1->totrct.ymax, jd->sa2->totrct.ymax); + float inner[4] = {1.0f, 1.0f, 1.0f, 0.1f}; + float outline[4] = {1.0f, 1.0f, 1.0f, 0.3f}; + screen_animate_area_highlight( + CTX_wm_window(C), screen, &combined, inner, outline, AREA_JOIN_FADEOUT); + if (!screen_area_join(C, op->reports, screen, jd->sa1, jd->sa2)) { return false; } @@ -3971,6 +3999,13 @@ void static area_docking_apply(bContext *C, wmOperator *op) return; } + float inner[4] = {1.0f, 1.0f, 1.0f, 0.15f}; + float outline[4] = {1.0f, 1.0f, 1.0f, 0.4f}; + jd->sa2->flag |= AREA_FLAG_REGION_SIZE_UPDATE; + ED_area_update_region_sizes(CTX_wm_manager(C), jd->win2, jd->sa2); + screen_animate_area_highlight( + jd->win2, CTX_wm_screen(C), &jd->sa2->totrct, inner, outline, AREA_DOCK_FADEOUT); + if (!aligned_neighbors || !screen_area_join(C, op->reports, CTX_wm_screen(C), jd->sa1, jd->sa2)) { ED_area_swapspace(C, jd->sa2, jd->sa1); @@ -3984,6 +4019,9 @@ void static area_docking_apply(bContext *C, wmOperator *op) WM_window_get_active_screen(jd->win2)->active_region = nullptr; } else { + float inner[4] = {0.0f, 0.0f, 0.0f, 0.7f}; + screen_animate_area_highlight( + jd->win1, CTX_wm_screen(C), &jd->sa1->totrct, inner, nullptr, AREA_CLOSE_FADEOUT); screen_area_close(C, op->reports, CTX_wm_screen(C), jd->sa1); } } @@ -4416,6 +4454,10 @@ static wmOperatorStatus area_join_modal(bContext *C, wmOperator *op, const wmEve else if (jd->sa1 && jd->sa1 == jd->sa2) { /* Same area so split. */ if (area_split_allowed(jd->sa1, jd->split_dir) && jd->split_fac > 0.0001) { + float inner[4] = {1.0f, 1.0f, 1.0f, 0.1f}; + float outline[4] = {1.0f, 1.0f, 1.0f, 0.3f}; + screen_animate_area_highlight( + jd->win1, CTX_wm_screen(C), &jd->sa1->totrct, inner, outline, AREA_SPLIT_FADEOUT); jd->sa2 = area_split(jd->win2, WM_window_get_active_screen(jd->win1), jd->sa1, diff --git a/source/blender/windowmanager/intern/wm_draw.cc b/source/blender/windowmanager/intern/wm_draw.cc index 4b525a55b83..9d5d506cb4c 100644 --- a/source/blender/windowmanager/intern/wm_draw.cc +++ b/source/blender/windowmanager/intern/wm_draw.cc @@ -632,7 +632,8 @@ void WM_draw_cb_exit(wmWindow *win, void *handle) static void wm_draw_callbacks(wmWindow *win) { - LISTBASE_FOREACH (WindowDrawCB *, wdc, &win->drawcalls) { + /* Allow callbacks to remove themselves. */ + LISTBASE_FOREACH_MUTABLE (WindowDrawCB *, wdc, &win->drawcalls) { wdc->draw(win, wdc->customdata); } }