UI: Fade In Some Area Maintenance Overlays

This adds a slight ease-in fade in to the start of some area
maintenance operations. Fade in the highlighting of join areas, docking
targets, closed areas, etc.

Pull Request: https://projects.blender.org/blender/blender/pulls/140319
This commit is contained in:
Harley Acheson
2025-07-29 23:36:05 +02:00
committed by Harley Acheson
parent 37a11ad824
commit e154175a90
3 changed files with 63 additions and 28 deletions

View File

@@ -380,21 +380,23 @@ static void screen_draw_area_drag_tip(
BLF_draw(fstyle->uifont_id, area_name, BLF_DRAW_STR_DUMMY_MAX);
}
static void screen_draw_area_closed(int xmin, int xmax, int ymin, int ymax)
static void screen_draw_area_closed(int xmin, int xmax, int ymin, int ymax, float anim_factor)
{
/* Darken the area. */
rctf rect = {float(xmin), float(xmax), float(ymin), float(ymax)};
float darken[4] = {0.0f, 0.0f, 0.0f, 0.7f};
float darken[4] = {0.0f, 0.0f, 0.0f, 0.7f * anim_factor};
UI_draw_roundbox_corner_set(UI_CNR_ALL);
UI_draw_roundbox_4fv_ex(&rect, darken, nullptr, 1.0f, nullptr, U.pixelsize, EDITORRADIUS);
}
void screen_draw_join_highlight(const wmWindow *win, ScrArea *sa1, ScrArea *sa2, eScreenDir dir)
void screen_draw_join_highlight(
const wmWindow *win, ScrArea *sa1, ScrArea *sa2, eScreenDir dir, float anim_factor)
{
if (dir == SCREEN_DIR_NONE || !sa2) {
/* Darken source if docking. Done here because it might be a different window. */
/* Darken source if docking. Done here because it might be a different window.
* Do not animate this as we don't want to reset every time we change areas. */
screen_draw_area_closed(
sa1->totrct.xmin, sa1->totrct.xmax, sa1->totrct.ymin, sa1->totrct.ymax);
sa1->totrct.xmin, sa1->totrct.xmax, sa1->totrct.ymin, sa1->totrct.ymax, 1.0f);
return;
}
@@ -418,45 +420,45 @@ void screen_draw_join_highlight(const wmWindow *win, ScrArea *sa1, ScrArea *sa2,
if (vertical) {
if (sa1->totrct.xmin < combined.xmin) {
screen_draw_area_closed(
sa1->totrct.xmin, combined.xmin, sa1->totrct.ymin, sa1->totrct.ymax);
sa1->totrct.xmin, combined.xmin, sa1->totrct.ymin, sa1->totrct.ymax, anim_factor);
}
if (sa2->totrct.xmin < combined.xmin) {
screen_draw_area_closed(
sa2->totrct.xmin, combined.xmin, sa2->totrct.ymin, sa2->totrct.ymax);
sa2->totrct.xmin, combined.xmin, sa2->totrct.ymin, sa2->totrct.ymax, anim_factor);
}
if (sa1->totrct.xmax > combined.xmax) {
screen_draw_area_closed(
combined.xmax, sa1->totrct.xmax, sa1->totrct.ymin, sa1->totrct.ymax);
combined.xmax, sa1->totrct.xmax, sa1->totrct.ymin, sa1->totrct.ymax, anim_factor);
}
if (sa2->totrct.xmax > combined.xmax) {
screen_draw_area_closed(
combined.xmax, sa2->totrct.xmax, sa2->totrct.ymin, sa2->totrct.ymax);
combined.xmax, sa2->totrct.xmax, sa2->totrct.ymin, sa2->totrct.ymax, anim_factor);
}
}
else {
if (sa1->totrct.ymin < combined.ymin) {
screen_draw_area_closed(
sa1->totrct.xmin, sa1->totrct.xmax, sa1->totrct.ymin, combined.ymin);
sa1->totrct.xmin, sa1->totrct.xmax, sa1->totrct.ymin, combined.ymin, anim_factor);
}
if (sa2->totrct.ymin < combined.ymin) {
screen_draw_area_closed(
sa2->totrct.xmin, sa2->totrct.xmax, sa2->totrct.ymin, combined.ymin);
sa2->totrct.xmin, sa2->totrct.xmax, sa2->totrct.ymin, combined.ymin, anim_factor);
}
if (sa1->totrct.ymax > combined.ymax) {
screen_draw_area_closed(
sa1->totrct.xmin, sa1->totrct.xmax, combined.ymax, sa1->totrct.ymax);
sa1->totrct.xmin, sa1->totrct.xmax, combined.ymax, sa1->totrct.ymax, anim_factor);
}
if (sa2->totrct.ymax > combined.ymax) {
screen_draw_area_closed(
sa2->totrct.xmin, sa2->totrct.xmax, combined.ymax, sa2->totrct.ymax);
sa2->totrct.xmin, sa2->totrct.xmax, combined.ymax, sa2->totrct.ymax, anim_factor);
}
}
}
/* Outline the combined area. */
UI_draw_roundbox_corner_set(UI_CNR_ALL);
float outline[4] = {1.0f, 1.0f, 1.0f, 0.4f};
float inner[4] = {1.0f, 1.0f, 1.0f, 0.10f};
float outline[4] = {1.0f, 1.0f, 1.0f, 0.4f * anim_factor};
float inner[4] = {1.0f, 1.0f, 1.0f, 0.10f * anim_factor};
UI_draw_roundbox_4fv_ex(&combined, inner, nullptr, 1.0f, outline, U.pixelsize, EDITORRADIUS);
screen_draw_area_drag_tip(
@@ -537,16 +539,18 @@ void screen_draw_dock_preview(const wmWindow *win,
AreaDockTarget dock_target,
float factor,
int x,
int y)
int y,
float anim_factor)
{
if (dock_target == AreaDockTarget::None) {
return;
}
float outline[4] = {1.0f, 1.0f, 1.0f, 0.4f};
float inner[4] = {1.0f, 1.0f, 1.0f, 0.1f};
float outline[4] = {1.0f, 1.0f, 1.0f, 0.4f * anim_factor};
float inner[4] = {1.0f, 1.0f, 1.0f, 0.1f * anim_factor};
float border[4];
UI_GetThemeColor4fv(TH_EDITOR_BORDER, border);
border[3] *= anim_factor;
UI_draw_roundbox_corner_set(UI_CNR_ALL);
float half_line_width = float(U.border_width) * UI_SCALE_FAC;

View File

@@ -80,8 +80,9 @@ 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_CLOSE_FADEOUT 0.15f /* seconds */
#define AREA_DOCK_FADEOUT 0.15f /* seconds */
#define AREA_DOCK_FADEIN 0.15f /* seconds */
#define AREA_JOIN_FADEOUT 0.15f /* seconds */
#define AREA_SPLIT_FADEOUT 0.15f /* seconds */
@@ -103,14 +104,16 @@ void region_toggle_hidden(bContext *C, ARegion *region, bool do_fade);
* \param sa1: Area from which the resultant originates.
* \param sa2: Target area that will be replaced.
*/
void screen_draw_join_highlight(const wmWindow *win, ScrArea *sa1, ScrArea *sa2, eScreenDir dir);
void screen_draw_join_highlight(
const wmWindow *win, ScrArea *sa1, ScrArea *sa2, eScreenDir dir, float anim_factor);
void screen_draw_dock_preview(const wmWindow *win,
ScrArea *source,
ScrArea *target,
AreaDockTarget dock_target,
float factor,
int x,
int y);
int y,
float anim_factor);
void screen_draw_split_preview(ScrArea *area, eScreenAxis dir_axis, float factor);
void screen_draw_move_highlight(const wmWindow *win, bScreen *screen, eScreenAxis dir_axis);

View File

@@ -16,6 +16,7 @@
#include "BLI_listbase.h"
#include "BLI_math_rotation.h"
#include "BLI_math_vector.h"
#include "BLI_time.h"
#include "BLI_utildefines.h"
#include "BLT_translation.hh"
@@ -3734,6 +3735,9 @@ struct sAreaJoinData {
float split_fac; /* Split factor in split_dir direction. */
wmWindow *win1; /* Window of source area. */
wmWindow *win2; /* Window of the target area. */
bScreen *screen; /* Screen of the source area. */
double start_time; /* Start time of animation. */
double end_time; /* End time of animation. */
wmWindow *draw_dock_win; /* Window getting docking highlight. */
bool close_win; /* Close the source window when done. */
void *draw_callback; /* call #screen_draw_join_highlight */
@@ -3748,11 +3752,18 @@ static void area_join_draw_cb(const wmWindow *win, void *userdata)
return;
}
float factor = 1.0f;
const double now = BLI_time_now_seconds();
if (now < sd->end_time) {
factor = pow((now - sd->start_time) / (sd->end_time - sd->start_time), 2);
sd->screen->do_refresh = true;
}
if (sd->sa1 == sd->sa2) {
screen_draw_split_preview(sd->sa1, sd->split_dir, sd->split_fac);
}
else {
screen_draw_join_highlight(win, sd->sa1, sd->sa2, sd->dir);
screen_draw_join_highlight(win, sd->sa1, sd->sa2, sd->dir, factor);
}
}
@@ -3763,8 +3774,16 @@ static void area_join_dock_cb(const wmWindow *win, void *userdata)
if (!jd || !jd->sa2 || jd->dir != SCREEN_DIR_NONE || jd->sa1 == jd->sa2) {
return;
}
float factor = 1.0f;
const double now = BLI_time_now_seconds();
if (now < jd->end_time) {
factor = pow((now - jd->start_time) / (jd->end_time - jd->start_time), 2);
jd->screen->do_refresh = true;
}
screen_draw_dock_preview(
win, jd->sa1, jd->sa2, jd->dock_target, jd->factor, jd->current_x, jd->current_y);
win, jd->sa1, jd->sa2, jd->dock_target, jd->factor, jd->current_x, jd->current_y, factor);
}
static void area_join_dock_cb_window(sAreaJoinData *jd, wmOperator *op)
@@ -3818,6 +3837,9 @@ static bool area_join_init(bContext *C, wmOperator *op, ScrArea *sa1, ScrArea *s
jd->dir = area_getorientation(sa1, sa2);
jd->win1 = WM_window_find_by_area(CTX_wm_manager(C), sa1);
jd->win2 = WM_window_find_by_area(CTX_wm_manager(C), sa2);
jd->screen = CTX_wm_screen(C);
jd->start_time = BLI_time_now_seconds();
jd->end_time = jd->start_time + AREA_DOCK_FADEIN;
op->customdata = jd;
return true;
@@ -4335,9 +4357,14 @@ static void area_join_update_data(bContext *C, sAreaJoinData *jd, const wmEvent
jd->win2 = WM_window_find_by_area(CTX_wm_manager(C), jd->sa2);
jd->dir = SCREEN_DIR_NONE;
jd->dock_target = AreaDockTarget::None;
jd->dir = area_getorientation(jd->sa1, jd->sa2);
jd->dir = area_getorientation(jd->sa1, area);
jd->dock_target = area_docking_target(jd, event);
if (jd->sa2 != area) {
jd->start_time = BLI_time_now_seconds();
jd->end_time = jd->start_time + AREA_DOCK_FADEIN;
}
if (jd->sa1 == area) {
const int drag_threshold = 30 * UI_SCALE_FAC;
jd->sa2 = area;
@@ -4351,9 +4378,10 @@ static void area_join_update_data(bContext *C, sAreaJoinData *jd, const wmEvent
return;
}
jd->split_dir = (abs(event->xy[0] - jd->start_x) > abs(event->xy[1] - jd->start_y)) ?
SCREEN_AXIS_V :
SCREEN_AXIS_H;
eScreenAxis dir = (abs(event->xy[0] - jd->start_x) > abs(event->xy[1] - jd->start_y)) ?
SCREEN_AXIS_V :
SCREEN_AXIS_H;
jd->split_dir = dir;
jd->split_fac = area_split_factor(C, jd, event);
return;
}