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:
committed by
Harley Acheson
parent
df0564f3b8
commit
ae3bf84f35
@@ -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. */
|
||||
|
||||
@@ -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` */
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user