UI: Docking Interactive Resizing

This is a change to the docking process so that the target area SIZE
can be specified at the same time as selecting the location. This also
changes to a drag-and-drop style of mouse pointer indication.

Pull Request: https://projects.blender.org/blender/blender/pulls/126447
This commit is contained in:
Harley Acheson
2024-08-22 02:38:46 +02:00
committed by Harley Acheson
parent df0564f3b8
commit ae3bf84f35
3 changed files with 75 additions and 63 deletions

View File

@@ -219,36 +219,33 @@ void ED_screen_draw_edges(wmWindow *win)
}
}
static void screen_draw_area_icon(rctf *rect, int icon, uchar *color, float *bg_color = nullptr)
static void screen_draw_area_icon(int x, int y, int icon)
{
if (!U.experimental.use_docking) {
return;
}
if (BLI_rctf_size_x(rect) < UI_SCALE_FAC * 75.0f || BLI_rctf_size_y(rect) < UI_SCALE_FAC * 60.0f)
{
return;
}
const float bg_width = UI_SCALE_FAC * 35.0f;
const float bg_height = UI_SCALE_FAC * 40.0f;
const float center_x = BLI_rctf_cent_x(rect);
const float center_y = BLI_rctf_cent_y(rect);
const float bg_color[4] = {0.9f, 0.9f, 0.9f, 1.0f};
const float outline[4] = {0.0f, 0.0f, 0.0f, 0.4f};
const rctf bg_rect = {
/*xmin*/ x - (bg_width / 2.0f),
/*xmax*/ x + bg_width - (bg_width / 2.0f),
/*ymin*/ y - (bg_height / 2.0f),
/*ymax*/ y + bg_height - (bg_height / 2.0f),
};
if (bg_color) {
const float bg_width = UI_SCALE_FAC * 50.0f;
const float bg_height = UI_SCALE_FAC * 40.0f;
const rctf bg_rect = {
/*xmin*/ center_x - (bg_width / 2.0f),
/*xmax*/ center_x + bg_width - (bg_width / 2.0f),
/*ymin*/ center_y - (bg_height / 2.0f),
/*ymax*/ center_y + bg_height - (bg_height / 2.0f),
};
UI_draw_roundbox_4fv_ex(
&bg_rect, bg_color, nullptr, 1.0f, nullptr, U.pixelsize, 6 * U.pixelsize);
}
ui_draw_dropshadow(&bg_rect, 4 * U.pixelsize, 6 * U.pixelsize, 1.0f, 0.3f);
const float icon_size = 32.0f * UI_SCALE_FAC;
UI_icon_draw_ex(center_x - (icon_size / 2.0f),
center_y - (icon_size / 2.0f),
UI_draw_roundbox_4fv_ex(
&bg_rect, bg_color, nullptr, 1.0f, outline, U.pixelsize, 4 * U.pixelsize);
const float icon_size = 24.0f * UI_SCALE_FAC;
const uchar color[4] = {0, 0, 0, 220};
UI_icon_draw_ex(x - (icon_size / 2.0f),
y - (icon_size / 2.0f),
icon,
16.0f / icon_size,
float(color[3]) / 255.0f,
@@ -267,7 +264,7 @@ static void screen_draw_area_closed(int xmin, int xmax, int ymin, int ymax)
UI_draw_roundbox_4fv_ex(&rect, darken, nullptr, 1.0f, nullptr, U.pixelsize, 6 * U.pixelsize);
}
void screen_draw_join_highlight(ScrArea *sa1, ScrArea *sa2, eScreenDir dir)
void screen_draw_join_highlight(const wmWindow *win, ScrArea *sa1, ScrArea *sa2, eScreenDir dir)
{
if (dir == SCREEN_DIR_NONE || !sa2) {
/* Darken source if docking. Done here because it might be a different window. */
@@ -359,21 +356,14 @@ void screen_draw_join_highlight(ScrArea *sa1, ScrArea *sa2, eScreenDir dir)
float inner[4] = {1.0f, 1.0f, 1.0f, 0.10f};
UI_draw_roundbox_4fv_ex(&combined, inner, nullptr, 1.0f, outline, U.pixelsize, 6 * U.pixelsize);
/* Icon in center of intersection of combined and sa2 - the subsumed part. */
rctf sa2tot;
BLI_rctf_rcti_copy(&sa2tot, &sa2->totrct);
rctf sa2new;
BLI_rctf_isect(&combined, &sa2tot, &sa2new);
uchar icon_color[4] = {255, 255, 255, 255};
float bg_color[4] = {0.0f, 0.0f, 0.0f, 0.4f};
screen_draw_area_icon(&sa2new, ED_area_icon(sa1), icon_color, bg_color);
screen_draw_area_icon(win->eventstate->xy[0], win->eventstate->xy[1], ED_area_icon(sa1));
}
void screen_draw_dock_preview(const wmWindow * /*win*/,
void screen_draw_dock_preview(const wmWindow *win,
ScrArea *source,
ScrArea *target,
AreaDockTarget dock_target)
AreaDockTarget dock_target,
float factor)
{
if (dock_target == AreaDockTarget::None) {
return;
@@ -381,8 +371,6 @@ void screen_draw_dock_preview(const wmWindow * /*win*/,
float outline[4] = {1.0f, 1.0f, 1.0f, 0.4f};
float inner[4] = {1.0f, 1.0f, 1.0f, 0.1f};
float bg_color[4] = {0.0f, 0.0f, 0.0f, 0.4f};
uchar icon_color[4] = {255, 255, 255, 255};
float border[4];
UI_GetThemeColor4fv(TH_EDITOR_OUTLINE, border);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
@@ -396,28 +384,33 @@ void screen_draw_dock_preview(const wmWindow * /*win*/,
float split;
if (dock_target == AreaDockTarget::Right) {
split = std::min(dest.xmin + target->winx * 0.501f, dest.xmax - AREAMINX * UI_SCALE_FAC);
split = std::min(dest.xmin + target->winx * (1.0f - factor),
dest.xmax - AREAMINX * UI_SCALE_FAC);
dest.xmin = split + half_line_width;
remainder.xmax = split - half_line_width;
}
else if (dock_target == AreaDockTarget::Left) {
split = std::max(dest.xmax - target->winx * 0.501f, dest.xmin + AREAMINX * UI_SCALE_FAC);
split = std::max(dest.xmax - target->winx * (1.0f - factor),
dest.xmin + AREAMINX * UI_SCALE_FAC);
dest.xmax = split - half_line_width;
remainder.xmin = split + half_line_width;
}
else if (dock_target == AreaDockTarget::Top) {
split = std::min(dest.ymin + target->winy * 0.501f, dest.ymax - HEADERY * UI_SCALE_FAC);
split = std::min(dest.ymin + target->winy * (1.0f - factor),
dest.ymax - HEADERY * UI_SCALE_FAC);
dest.ymin = split + half_line_width;
remainder.ymax = split - half_line_width;
}
else if (dock_target == AreaDockTarget::Bottom) {
split = std::max(dest.ymax - target->winy * 0.501f, dest.ymin + HEADERY * UI_SCALE_FAC);
split = std::max(dest.ymax - target->winy * (1.0f - factor),
dest.ymin + HEADERY * UI_SCALE_FAC);
dest.ymax = split - half_line_width;
remainder.ymin = split + half_line_width;
}
UI_draw_roundbox_4fv_ex(&dest, inner, nullptr, 1.0f, outline, U.pixelsize, 6 * U.pixelsize);
screen_draw_area_icon(&dest, ED_area_icon(source), icon_color, bg_color);
screen_draw_area_icon(win->eventstate->xy[0], win->eventstate->xy[1], ED_area_icon(source));
if (dock_target != AreaDockTarget::Center) {
/* Darken the split position itself. */

View File

@@ -88,11 +88,9 @@ 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(ScrArea *sa1, ScrArea *sa2, eScreenDir dir);
void screen_draw_dock_preview(const wmWindow *win,
ScrArea *source,
ScrArea *target,
AreaDockTarget dock_target);
void screen_draw_join_highlight(const wmWindow *win, ScrArea *sa1, ScrArea *sa2, eScreenDir dir);
void screen_draw_dock_preview(
const wmWindow *win, ScrArea *source, ScrArea *target, AreaDockTarget dock_target, float fac);
void screen_draw_split_preview(ScrArea *area, eScreenAxis dir_axis, float fac);
/* `screen_edit.cc` */

View File

@@ -3557,6 +3557,7 @@ struct sAreaJoinData {
eScreenDir dir; /* Direction of potential join. */
eScreenAxis split_dir; /* Direction of split within the source area. */
AreaDockTarget dock_target; /* Position within target we are pointing to. */
float factor; /* dock target size can vary. */
int x, y; /* Starting mouse position. */
float split_fac; /* Split factor in split_dir direction. */
wmWindow *win1; /* Window of source area. */
@@ -3567,7 +3568,7 @@ struct sAreaJoinData {
void *draw_dock_callback; /* call #screen_draw_dock_highlight, overlay on draw_dock_win. */
};
static void area_join_draw_cb(const wmWindow * /*win*/, void *userdata)
static void area_join_draw_cb(const wmWindow *win, void *userdata)
{
const wmOperator *op = static_cast<const wmOperator *>(userdata);
sAreaJoinData *sd = static_cast<sAreaJoinData *>(op->customdata);
@@ -3579,7 +3580,7 @@ static void area_join_draw_cb(const wmWindow * /*win*/, void *userdata)
screen_draw_split_preview(sd->sa1, sd->split_dir, sd->split_fac);
}
else {
screen_draw_join_highlight(sd->sa1, sd->sa2, sd->dir);
screen_draw_join_highlight(win, sd->sa1, sd->sa2, sd->dir);
}
}
@@ -3590,7 +3591,7 @@ 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;
}
screen_draw_dock_preview(win, jd->sa1, jd->sa2, jd->dock_target);
screen_draw_dock_preview(win, jd->sa1, jd->sa2, jd->dock_target, jd->factor);
}
static void area_join_dock_cb_window(sAreaJoinData *jd, wmOperator *op)
@@ -3758,11 +3759,18 @@ void static area_docking_apply(bContext *C, wmOperator *op)
eScreenAxis dir = (ELEM(jd->dock_target, AreaDockTarget::Left, AreaDockTarget::Right)) ?
SCREEN_AXIS_V :
SCREEN_AXIS_H;
float fac = ELEM(jd->dock_target, AreaDockTarget::Left, AreaDockTarget::Bottom) ? 0.49999f :
0.50001f;
float fac = jd->factor;
if (ELEM(jd->dock_target, AreaDockTarget::Right, AreaDockTarget::Top)) {
fac = 1.0f - fac;
}
ScrArea *newa = area_split(
jd->win2, WM_window_get_active_screen(jd->win2), jd->sa2, dir, fac, true);
jd->sa2 = newa;
if (jd->factor <= 0.5f) {
jd->sa2 = newa;
}
}
if (same_area) {
@@ -3809,24 +3817,29 @@ static int area_join_cursor(sAreaJoinData *jd, const wmEvent *event)
}
if (jd->dock_target == AreaDockTarget::None) {
if (jd->dir == SCREEN_DIR_N) {
return WM_CURSOR_N_ARROW;
if (U.experimental.use_docking) {
return WM_CURSOR_NONE;
}
if (jd->dir == SCREEN_DIR_S) {
return WM_CURSOR_S_ARROW;
}
if (jd->dir == SCREEN_DIR_W) {
return WM_CURSOR_W_ARROW;
}
if (jd->dir == SCREEN_DIR_E) {
return WM_CURSOR_E_ARROW;
else {
if (jd->dir == SCREEN_DIR_N) {
return WM_CURSOR_N_ARROW;
}
if (jd->dir == SCREEN_DIR_S) {
return WM_CURSOR_S_ARROW;
}
if (jd->dir == SCREEN_DIR_W) {
return WM_CURSOR_W_ARROW;
}
if (jd->dir == SCREEN_DIR_E) {
return WM_CURSOR_E_ARROW;
}
}
}
if (U.experimental.use_docking &&
(jd->dir != SCREEN_DIR_NONE || jd->dock_target != AreaDockTarget::None))
{
return WM_CURSOR_PICK_AREA;
return WM_CURSOR_NONE;
}
return U.experimental.use_docking ? WM_CURSOR_PICK_AREA : WM_CURSOR_STOP;
@@ -3884,12 +3897,16 @@ static AreaDockTarget area_docking_target(sAreaJoinData *jd, const wmEvent *even
/* If we've made it here, then there can be no joining possible. */
jd->dir = SCREEN_DIR_NONE;
jd->factor = 0.5f;
float accel = (jd->sa1 == jd->sa2) ? 1.7f : 2.0f;
/* if the area is narrow then there are only two docking targets. */
if (jd->sa2->winx < min_x) {
jd->factor = float(y) / float(jd->sa2->winy) * accel;
return (y < jd->sa2->winy / 2) ? AreaDockTarget::Bottom : AreaDockTarget::Top;
}
if (jd->sa2->winy < min_y) {
jd->factor = float(x) / float(jd->sa2->winx) * accel;
return (x < jd->sa2->winx / 2) ? AreaDockTarget::Left : AreaDockTarget::Right;
}
@@ -3905,15 +3922,19 @@ static AreaDockTarget area_docking_target(sAreaJoinData *jd, const wmEvent *even
/* Split the area diagonally from top-left to bottom-right. */
const bool lower_left = float(x) / float(jd->sa2->winy - y + 1) < area_ratio;
if (upper_left && !lower_left) {
jd->factor = (1.0f - float(y) / float(jd->sa2->winy)) * accel;
return AreaDockTarget::Top;
}
if (!upper_left && lower_left) {
jd->factor = float(y) / float(jd->sa2->winy) * accel;
return AreaDockTarget::Bottom;
}
if (upper_left && lower_left) {
jd->factor = float(x) / float(jd->sa2->winx) * accel;
return AreaDockTarget::Left;
}
if (!upper_left && !lower_left) {
jd->factor = (1.0f - float(x) / float(jd->sa2->winx)) * accel;
return AreaDockTarget::Right;
}
return AreaDockTarget::None;