[Bf-blender-cvs] [c9ed78733cc] blender2.8: UI: fixes for 3D viewport popovers moving / flipping on edits.
Brecht Van Lommel
noreply at git.blender.org
Sun May 6 20:16:52 CEST 2018
Commit: c9ed78733cc99296e90434f085651cc83fe0a7d1
Author: Brecht Van Lommel
Date: Sun May 6 18:08:27 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBc9ed78733cc99296e90434f085651cc83fe0a7d1
UI: fixes for 3D viewport popovers moving / flipping on edits.
* Ensure popover does not change direction or location.
* Open popover towards the relevant editor, like pulldown menus.
* Use a bigger maximum assumed size to deal with some corner cases.
* Do proper 3D viewport header refresh on shading mode changes.
===================================================================
M source/blender/editors/interface/interface_intern.h
M source/blender/editors/interface/interface_region_popover.c
M source/blender/editors/interface/interface_region_popup.c
M source/blender/editors/interface/interface_widgets.c
M source/blender/editors/space_view3d/space_view3d.c
===================================================================
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index e6f40d758d1..de2217a3d3e 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -551,6 +551,7 @@ struct uiPopupBlockHandle {
struct uiPopupBlockCreate popup_create_vars;
/* true if we can re-create the popup using 'popup_create_vars' */
bool can_refresh;
+ bool refresh;
struct wmTimer *scrolltimer;
@@ -572,8 +573,14 @@ struct uiPopupBlockHandle {
/* menu direction */
int direction;
- /* previous rect for refresh */
+ /* Previous values so we don't resize or reposition on refresh. */
rctf prev_block_rect;
+ rctf prev_butrct;
+ short prev_dir1, prev_dir2;
+ int prev_mx, prev_my;
+
+ /* Maximum estimated size to avoid having to reposition on refresh. */
+ float max_size_x, max_size_y;
/* #ifdef USE_DRAG_POPUP */
bool is_grab;
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index dea09393504..4dfa9198958 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -57,6 +57,8 @@
#include "BKE_context.h"
+#include "ED_screen.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -122,7 +124,7 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
UI_block_region_set(block, handle->region);
UI_block_layout_resolve(block, &width, &height);
- UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_KEEP_OPEN | UI_BLOCK_POPOVER);
+ UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_KEEP_OPEN | UI_BLOCK_POPOVER | UI_BLOCK_NO_WIN_CLIP);
UI_block_direction_set(block, UI_DIR_DOWN | UI_DIR_CENTER_X);
const int block_margin = U.widget_unit / 2;
@@ -138,13 +140,32 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
UI_block_direction_set(block, UI_DIR_RIGHT);
/* Store the button location for positioning the popover arrow hint. */
- {
+ if (!handle->refresh) {
float center[2] = {BLI_rctf_cent_x(&pup->but->rect), BLI_rctf_cent_y(&pup->but->rect)};
ui_block_to_window_fl(handle->ctx_region, pup->but->block, ¢er[0], ¢er[1]);
/* These variables aren't used for popovers, we could add new variables if there is a conflict. */
- block->mx = (int)center[0];
- block->my = (int)center[1];
+ handle->prev_mx = block->mx = (int)center[0];
+ handle->prev_my = block->my = (int)center[1];
+ }
+ else {
+ block->mx = handle->prev_mx;
+ block->my = handle->prev_my;
}
+
+ /* Prefer popover from header to be positioned into the editor. */
+ if (!slideout) {
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa && ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) {
+ ARegion *ar = CTX_wm_region(C);
+ if (ar && ar->regiontype == RGN_TYPE_HEADER) {
+ UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
+ }
+ }
+ }
+
+ /* Estimated a maximum size so we don't go offscreen for low height
+ * areas near the bottom of the window on refreshes. */
+ handle->max_size_y = UI_UNIT_Y * 16.0f;
}
else {
/* Not attached to a button. */
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index cc194b41f1b..e971edb95cb 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -84,32 +84,38 @@ void ui_popup_translate(bContext *C, ARegion *ar, const int mdiff[2])
}
/* position block relative to but, result is in window space */
-static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, uiBlock *block)
+static void ui_popup_block_position(wmWindow *window, ARegion *butregion, uiBut *but, uiBlock *block)
{
- uiBut *bt;
- uiSafetyRct *saferct;
+ uiPopupBlockHandle *handle = block->handle;
+
+ /* Compute button position in window coordinates using the source
+ * button region/block, to position the popup attached to it. */
rctf butrct;
- /*float aspect;*/ /*UNUSED*/
- int size_x, size_y, offset_x = 0, offset_y = 0;
- short dir1 = 0, dir2 = 0;
- /* transform to window coordinates, using the source button region/block */
- ui_block_to_window_rctf(butregion, but->block, &butrct, &but->rect);
+ if (!handle->refresh) {
+ ui_block_to_window_rctf(butregion, but->block, &butrct, &but->rect);
+
+ /* widget_roundbox_set has this correction too, keep in sync */
+ if (but->type != UI_BTYPE_PULLDOWN) {
+ if (but->drawflag & UI_BUT_ALIGN_TOP)
+ butrct.ymax += U.pixelsize;
+ if (but->drawflag & UI_BUT_ALIGN_LEFT)
+ butrct.xmin -= U.pixelsize;
+ }
- /* widget_roundbox_set has this correction too, keep in sync */
- if (but->type != UI_BTYPE_PULLDOWN) {
- if (but->drawflag & UI_BUT_ALIGN_TOP)
- butrct.ymax += U.pixelsize;
- if (but->drawflag & UI_BUT_ALIGN_LEFT)
- butrct.xmin -= U.pixelsize;
+ handle->prev_butrct = butrct;
+ }
+ else {
+ /* For refreshes, keep same button position so popup doesn't move. */
+ butrct = handle->prev_butrct;
}
- /* calc block rect */
+ /* Compute block size in window space, based on buttons contained in it. */
if (block->rect.xmin == 0.0f && block->rect.xmax == 0.0f) {
if (block->buttons.first) {
BLI_rctf_init_minmax(&block->rect);
- for (bt = block->buttons.first; bt; bt = bt->next) {
+ for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
BLI_rctf_union(&block->rect, &bt->rect);
}
}
@@ -120,35 +126,34 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
}
}
- /* aspect = (float)(BLI_rcti_size_x(&block->rect) + 4);*/ /*UNUSED*/
ui_block_to_window_rctf(butregion, but->block, &block->rect, &block->rect);
- //block->rect.xmin -= 2.0; block->rect.ymin -= 2.0;
- //block->rect.xmax += 2.0; block->rect.ymax += 2.0;
+ /* Compute direction relative to button, based on available space. */
+ const int size_x = BLI_rctf_size_x(&block->rect) + 0.2f * UI_UNIT_X; /* 4 for shadow */
+ const int size_y = BLI_rctf_size_y(&block->rect) + 0.2f * UI_UNIT_Y;
+ const int center_x = (block->direction & UI_DIR_CENTER_X) ? size_x / 2 : 0;
+ const int center_y = (block->direction & UI_DIR_CENTER_Y) ? size_y / 2 : 0;
- size_x = BLI_rctf_size_x(&block->rect) + 0.2f * UI_UNIT_X; /* 4 for shadow */
- size_y = BLI_rctf_size_y(&block->rect) + 0.2f * UI_UNIT_Y;
- /* aspect /= (float)size_x;*/ /*UNUSED*/
+ short dir1 = 0, dir2 = 0;
- {
+ if (!handle->refresh) {
bool left = 0, right = 0, top = 0, down = 0;
- // int offscreen;
const int win_x = WM_window_pixels_x(window);
const int win_y = WM_window_pixels_y(window);
- // wm_window_get_size(window, &win_x, &win_y);
- const int center_x = (block->direction & UI_DIR_CENTER_X) ? size_x / 2 : 0;
- const int center_y = (block->direction & UI_DIR_CENTER_Y) ? size_y / 2 : 0;
+ /* Take into account maximum size so we don't have to flip on refresh. */
+ const float max_size_x = max_ff(size_x, handle->max_size_x);
+ const float max_size_y = max_ff(size_y, handle->max_size_y);
/* check if there's space at all */
- if (butrct.xmin - size_x + center_x > 0.0f) left = 1;
- if (butrct.xmax + size_x - center_x < win_x) right = 1;
- if (butrct.ymin - size_y + center_y > 0.0f) down = 1;
- if (butrct.ymax + size_y - center_y < win_y) top = 1;
+ if (butrct.xmin - max_size_x + center_x > 0.0f) left = 1;
+ if (butrct.xmax + max_size_x - center_x < win_x) right = 1;
+ if (butrct.ymin - max_size_y + center_y > 0.0f) down = 1;
+ if (butrct.ymax + max_size_y - center_y < win_y) top = 1;
if (top == 0 && down == 0) {
- if (butrct.ymin - size_y < win_y - butrct.ymax - size_y)
+ if (butrct.ymin - max_size_y < win_y - butrct.ymax - max_size_y)
top = 1;
else
down = 1;
@@ -182,70 +187,57 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
if (dir2 == UI_DIR_DOWN && down == 0) dir2 = UI_DIR_UP;
}
- if (dir1 == UI_DIR_LEFT) {
- offset_x = butrct.xmin - block->rect.xmax;
- if (dir2 == UI_DIR_UP) offset_y = butrct.ymin - block->rect.ymin - center_y - MENU_PADDING;
- else offset_y = butrct.ymax - block->rect.ymax + center_y + MENU_PADDING;
- }
- else if (dir1 == UI_DIR_RIGHT) {
- offset_x = butrct.xmax - block->rect.xmin;
- if (dir2 == UI_DIR_UP) offset_y = butrct.ymin - block->rect.ymin - center_y - MENU_PADDING;
- else offset_y = butrct.ymax - block->rect.ymax + center_y + MENU_PADDING;
- }
- else if (dir1 == UI_DIR_UP) {
- offset_y = butrct.ymax - block->rect.ymin;
- if (dir2 == UI_DIR_RIGHT) offset_x = butrct.xmax - block->rect.xmax + center_x;
- else offset_x = butrct.xmin - block->rect.xmin - center_x;
- /* changed direction? */
- if ((dir1 & block->direction) == 0) {
- UI_block_order_flip(block);
- }
- }
- else if (dir1 == UI_DIR_DOWN) {
- offset_y = butrct.ymin - block->rect.ymax;
- if (dir2 == UI_DIR_RIGHT) offset_x = butrct.xmax - block->rect.xmax + center_x;
- else offset_x = butrct.xmin - block->rect.xmin - center_x;
- /* changed direction? */
- if ((dir1 & block->direction) == 0) {
- UI_block_order_flip(block);
- }
- }
+ handle->prev_dir1 = dir1;
+ handle->prev_dir2 = dir2;
+ }
+ else {
+ /* For refreshes, keep same popup direct so popup doesn't move
+ * to a totally different position while editing in it. */
+ dir1 = handle->prev_dir1;
+ dir2 = handle->prev_dir2;
+ }
- /* Center over popovers for eg. */
- if (block->direction & UI_DIR_CENTER_X) {
- offset_x += BLI_rctf_size_x(&butrct) / ((dir2 == UI_DIR_LEFT) ? 2 : - 2);
- }
+ /* Compute offset based on direction. */
+ int offset_x = 0, offset_y = 0;
- /* and now we handle the exception; no space below or to top */
- if (top == 0 && down == 0) {
- if (dir1 == UI_DIR_LEFT || dir1 == UI_DIR_RIGHT) {
- /* align with bottom of screen */
- // offset_y = size_y; (not with menu scrolls)
- }
+ if (dir1 == UI_DIR_LEFT) {
+ offset_x = butrct.xmin - block->rect.xmax;
+ if (di
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list