Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/interface')
-rw-r--r--source/blender/editors/interface/CMakeLists.txt5
-rw-r--r--source/blender/editors/interface/interface.c717
-rw-r--r--source/blender/editors/interface/interface_align.c54
-rw-r--r--source/blender/editors/interface/interface_anim.c75
-rw-r--r--source/blender/editors/interface/interface_context_menu.c206
-rw-r--r--source/blender/editors/interface/interface_draw.c1882
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c10
-rw-r--r--source/blender/editors/interface/interface_eyedropper_color.c4
-rw-r--r--source/blender/editors/interface/interface_eyedropper_datablock.c4
-rw-r--r--source/blender/editors/interface/interface_eyedropper_depth.c13
-rw-r--r--source/blender/editors/interface/interface_eyedropper_driver.c8
-rw-r--r--source/blender/editors/interface/interface_handlers.c524
-rw-r--r--source/blender/editors/interface/interface_icons.c837
-rw-r--r--source/blender/editors/interface/interface_icons_event.c295
-rw-r--r--source/blender/editors/interface/interface_intern.h168
-rw-r--r--source/blender/editors/interface/interface_layout.c1231
-rw-r--r--source/blender/editors/interface/interface_ops.c223
-rw-r--r--source/blender/editors/interface/interface_panel.c755
-rw-r--r--source/blender/editors/interface/interface_query.c28
-rw-r--r--source/blender/editors/interface/interface_region_hud.c339
-rw-r--r--source/blender/editors/interface/interface_region_menu_pie.c3
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.c21
-rw-r--r--source/blender/editors/interface/interface_region_popover.c396
-rw-r--r--source/blender/editors/interface/interface_region_popup.c267
-rw-r--r--source/blender/editors/interface/interface_region_search.c42
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c235
-rw-r--r--source/blender/editors/interface/interface_regions.c3
-rw-r--r--source/blender/editors/interface/interface_style.c27
-rw-r--r--source/blender/editors/interface/interface_templates.c1023
-rw-r--r--source/blender/editors/interface/interface_utils.c159
-rw-r--r--source/blender/editors/interface/interface_widgets.c2289
-rw-r--r--source/blender/editors/interface/resources.c1606
-rw-r--r--source/blender/editors/interface/view2d.c377
-rw-r--r--source/blender/editors/interface/view2d_ops.c66
34 files changed, 8798 insertions, 5094 deletions
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index 2c984d64266..cf172441be1 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -24,6 +24,8 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../depsgraph
+ ../../draw
../../gpu
../../imbuf
../../makesdna
@@ -52,13 +54,16 @@ set(SRC
interface_eyedropper_driver.c
interface_handlers.c
interface_icons.c
+ interface_icons_event.c
interface_layout.c
interface_ops.c
interface_panel.c
interface_query.c
interface_region_color_picker.c
+ interface_region_hud.c
interface_region_menu_pie.c
interface_region_menu_popup.c
+ interface_region_popover.c
interface_region_popup.c
interface_region_search.c
interface_region_tooltip.c
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 82ae4de07af..6df54c0a31c 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -41,6 +41,7 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
@@ -50,6 +51,7 @@
#include "BLI_utildefines.h"
+#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_idprop.h"
#include "BKE_main.h"
@@ -57,27 +59,37 @@
#include "BKE_screen.h"
#include "BKE_unit.h"
-#include "BIF_gl.h"
+#include "GPU_glew.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "BLF_api.h"
#include "BLT_translation.h"
#include "UI_interface.h"
+#include "UI_interface_icons.h"
#include "IMB_imbuf.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "wm_subwindow.h"
+#include "WM_message.h"
#include "RNA_access.h"
#include "BPY_extern.h"
+#include "ED_screen.h"
+
#include "IMB_colormanagement.h"
+#include "DEG_depsgraph_query.h"
+
#include "interface_intern.h"
+/* prototypes. */
+static void ui_but_to_pixelrect(struct rcti *rect, const struct ARegion *ar, struct uiBlock *block, struct uiBut *but);
+
/* avoid unneeded calls to ui_but_value_get */
#define UI_BUT_VALUE_UNSET DBL_MAX
#define UI_GET_BUT_VALUE_INIT(_but, _value) if (_value == DBL_MAX) { (_value) = ui_but_value_get(_but); } (void)0
@@ -205,6 +217,84 @@ void ui_region_to_window(const ARegion *ar, int *x, int *y)
*y += ar->winrct.ymin;
}
+static void ui_update_flexible_spacing(const ARegion *region, uiBlock *block)
+{
+ int sepr_flex_len = 0;
+ for (uiBut *but = block->buttons.first; but; but = but->next) {
+ if (but->type == UI_BTYPE_SEPR_SPACER) {
+ sepr_flex_len++;
+ }
+ }
+
+ if (sepr_flex_len == 0) {
+ return;
+ }
+
+ rcti rect;
+ ui_but_to_pixelrect(&rect, region, block, block->buttons.last);
+ const float buttons_width = (float)rect.xmax + UI_HEADER_OFFSET;
+ const float region_width = (float)region->sizex * U.dpi_fac;
+
+ if (region_width <= buttons_width) {
+ return;
+ }
+
+ /* We could get rid of this loop if we agree on a max number of spacer */
+ int *spacers_pos = alloca(sizeof(*spacers_pos) * (size_t)sepr_flex_len);
+ int i = 0;
+ for (uiBut *but = block->buttons.first; but; but = but->next) {
+ if (but->type == UI_BTYPE_SEPR_SPACER) {
+ ui_but_to_pixelrect(&rect, region, block, but);
+ spacers_pos[i] = rect.xmax + UI_HEADER_OFFSET;
+ i++;
+ }
+ }
+
+ const float segment_width = region_width / (float)sepr_flex_len;
+ float offset = 0, remaining_space = region_width - buttons_width;
+ i = 0;
+ for (uiBut *but = block->buttons.first; but; but = but->next) {
+ BLI_rctf_translate(&but->rect, offset, 0);
+ if (but->type == UI_BTYPE_SEPR_SPACER) {
+ /* How much the next block overlap with the current segment */
+ int overlap = (
+ (i == sepr_flex_len - 1) ?
+ buttons_width - spacers_pos[i] :
+ (spacers_pos[i + 1] - spacers_pos[i]) / 2);
+ int segment_end = segment_width * (i + 1);
+ int spacer_end = segment_end - overlap;
+ int spacer_sta = spacers_pos[i] + offset;
+ if (spacer_end > spacer_sta) {
+ float step = min_ff(remaining_space, spacer_end - spacer_sta);
+ remaining_space -= step;
+ offset += step;
+ }
+ i++;
+ }
+ }
+ ui_block_bounds_calc(block);
+}
+
+static void ui_update_window_matrix(const wmWindow *window, const ARegion *region, uiBlock *block)
+{
+ /* window matrix and aspect */
+ if (region && region->visible) {
+ /* Get projection matrix which includes View2D translation and zoom. */
+ gpuGetProjectionMatrix(block->winmat);
+ block->aspect = 2.0f / fabsf(region->winx * block->winmat[0][0]);
+ }
+ else {
+ /* No subwindow created yet, for menus for example, so we use the main
+ * window instead, since buttons are created there anyway. */
+ int width = WM_window_pixels_x(window);
+ int height = WM_window_pixels_y(window);
+ rcti winrct = {0, width - 1, 0, height - 1};
+
+ wmGetProjectionMatrix(block->winmat, &winrct);
+ block->aspect = 2.0f / fabsf(width * block->winmat[0][0]);
+ }
+}
+
/**
* Popups will add a margin to #ARegion.winrct for shadow,
* for interactivity (point-inside tests for eg), we want the winrct without the margin added.
@@ -223,7 +313,7 @@ void ui_region_winrct_get_no_margin(const struct ARegion *ar, struct rcti *r_rec
/* ******************* block calc ************************* */
-void ui_block_translate(uiBlock *block, int x, int y)
+void UI_block_translate(uiBlock *block, int x, int y)
{
uiBut *but;
@@ -243,7 +333,7 @@ static void ui_block_bounds_calc_text(uiBlock *block, float offset)
UI_fontstyle_set(&style->widget);
for (init_col_bt = bt = block->buttons.first; bt; bt = bt->next) {
- if (!ELEM(bt->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) {
+ if (!ELEM(bt->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER)) {
j = BLF_width(style->widget.uifont_id, bt->drawstr, sizeof(bt->drawstr));
if (j > i)
@@ -333,7 +423,7 @@ static void ui_block_bounds_calc_centered(wmWindow *window, uiBlock *block)
startx = (xmax * 0.5f) - (width * 0.5f);
starty = (ymax * 0.5f) - (height * 0.5f);
- ui_block_translate(block, startx - block->rect.xmin, starty - block->rect.ymin);
+ UI_block_translate(block, startx - block->rect.xmin, starty - block->rect.ymin);
/* now recompute bounds and safety */
ui_block_bounds_calc(block);
@@ -347,7 +437,7 @@ static void ui_block_bounds_calc_centered_pie(uiBlock *block)
block->pie_data.pie_center_spawned[1]
};
- ui_block_translate(block, xy[0], xy[1]);
+ UI_block_translate(block, xy[0], xy[1]);
/* now recompute bounds and safety */
ui_block_bounds_calc(block);
@@ -407,7 +497,7 @@ static void ui_block_bounds_calc_popup(
rect_bounds.ymax = ymax - UI_POPUP_MENU_TOP;
BLI_rcti_clamp(&rect, &rect_bounds, ofs_dummy);
- ui_block_translate(block, rect.xmin - block->rect.xmin, rect.ymin - block->rect.ymin);
+ UI_block_translate(block, rect.xmin - block->rect.xmin, rect.ymin - block->rect.ymin);
/* now recompute bounds and safety */
ui_block_bounds_calc(block);
@@ -491,86 +581,6 @@ static int ui_but_calc_float_precision(uiBut *but, double value)
return UI_calc_float_precision(prec, value);
}
-/* ************** LINK LINE DRAWING ************* */
-
-/* link line drawing is not part of buttons or theme.. so we stick with it here */
-
-static void ui_draw_linkline(uiLinkLine *line, int highlightActiveLines, int dashInactiveLines)
-{
- rcti rect;
-
- if (line->from == NULL || line->to == NULL) return;
-
- rect.xmin = BLI_rctf_cent_x(&line->from->rect);
- rect.ymin = BLI_rctf_cent_y(&line->from->rect);
- rect.xmax = BLI_rctf_cent_x(&line->to->rect);
- rect.ymax = BLI_rctf_cent_y(&line->to->rect);
-
- if (dashInactiveLines)
- UI_ThemeColor(TH_GRID);
- else if (line->flag & UI_SELECT)
- glColor3ub(100, 100, 100);
- else if (highlightActiveLines && ((line->from->flag & UI_ACTIVE) || (line->to->flag & UI_ACTIVE)))
- UI_ThemeColor(TH_TEXT_HI);
- else
- glColor3ub(0, 0, 0);
-
- ui_draw_link_bezier(&rect);
-}
-
-static void ui_draw_links(uiBlock *block)
-{
- uiBut *but;
- uiLinkLine *line;
-
- /* Draw the gray out lines. Do this first so they appear at the
- * bottom of inactive or active lines.
- * As we go, remember if we see any active or selected lines. */
- bool found_selectline = false;
- bool found_activeline = false;
-
- for (but = block->buttons.first; but; but = but->next) {
- if (but->type == UI_BTYPE_LINK && but->link) {
- for (line = but->link->lines.first; line; line = line->next) {
- if (!(line->from->flag & UI_ACTIVE) && !(line->to->flag & UI_ACTIVE)) {
- if (line->deactive)
- ui_draw_linkline(line, 0, true);
- }
- else
- found_activeline = true;
-
- if ((line->from->flag & UI_SELECT) || (line->to->flag & UI_SELECT))
- found_selectline = true;
- }
- }
- }
-
- /* Draw the inactive lines (lines with neither button being hovered over) */
- for (but = block->buttons.first; but; but = but->next) {
- if (but->type == UI_BTYPE_LINK && but->link) {
- for (line = but->link->lines.first; line; line = line->next) {
- if (!(line->from->flag & UI_ACTIVE) && !(line->to->flag & UI_ACTIVE)) {
- if (!line->deactive)
- ui_draw_linkline(line, 0, false);
- }
- }
- }
- }
-
- /* Draw any active lines (lines with either button being hovered over).
- * Do this last so they appear on top of inactive and gray out lines. */
- if (found_activeline) {
- for (but = block->buttons.first; but; but = but->next) {
- if (but->type == UI_BTYPE_LINK && but->link) {
- for (line = but->link->lines.first; line; line = line->next) {
- if ((line->from->flag & UI_ACTIVE) || (line->to->flag & UI_ACTIVE))
- ui_draw_linkline(line, !found_selectline, false);
- }
- }
- }
- }
-}
-
/* ************** BLOCK ENDING FUNCTION ************* */
/* NOTE: if but->poin is allocated memory for every defbut, things fail... */
@@ -613,38 +623,6 @@ uiBut *ui_but_find_new(uiBlock *block_new, const uiBut *but_old)
return but_new;
}
-/* oldbut is being inserted in new block, so we use the lines from new button, and replace button pointers */
-static void ui_but_update_linklines(uiBlock *block, uiBut *oldbut, uiBut *newbut)
-{
- uiLinkLine *line;
- uiBut *but;
-
- /* if active button is UI_BTYPE_LINK */
- if (newbut->type == UI_BTYPE_LINK && newbut->link) {
-
- SWAP(uiLink *, oldbut->link, newbut->link);
-
- for (line = oldbut->link->lines.first; line; line = line->next) {
- if (line->to == newbut)
- line->to = oldbut;
- if (line->from == newbut)
- line->from = oldbut;
- }
- }
-
- /* check all other button links */
- for (but = block->buttons.first; but; but = but->next) {
- if (but != newbut && but->type == UI_BTYPE_LINK && but->link) {
- for (line = but->link->lines.first; line; line = line->next) {
- if (line->to == newbut)
- line->to = oldbut;
- if (line->from == newbut)
- line->from = oldbut;
- }
- }
- }
-}
-
/**
* \return true when \a but_p is set (only done for active buttons).
*/
@@ -701,8 +679,6 @@ static bool ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBu
but->selend = oldbut->selend;
but->softmin = oldbut->softmin;
but->softmax = oldbut->softmax;
- but->linkto[0] = oldbut->linkto[0];
- but->linkto[1] = oldbut->linkto[1];
oldbut->active = NULL;
#endif
@@ -744,8 +720,6 @@ static bool ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBu
oldbut->a1 = but->a1;
}
- ui_but_update_linklines(block, oldbut, but);
-
if (!BLI_listbase_is_empty(&block->butstore)) {
UI_butstore_register_update(block, oldbut, but);
}
@@ -968,6 +942,7 @@ void ui_but_add_shortcut(uiBut *but, const char *shortcut_str, const bool do_str
MEM_freeN(butstr_orig);
but->str = but->strdata;
but->flag |= UI_BUT_HAS_SEP_CHAR;
+ but->drawflag |= UI_BUT_HAS_SHORTCUT;
ui_but_update(but);
}
}
@@ -1200,7 +1175,7 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
uiBut *but;
char buf[128];
- BLI_assert(block->flag & UI_BLOCK_LOOP);
+ BLI_assert(block->flag & (UI_BLOCK_LOOP | UI_BLOCK_SHOW_SHORTCUT_ALWAYS));
/* only do it before bounding */
if (block->rect.xmin != block->rect.xmax)
@@ -1216,7 +1191,13 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
}
else {
for (but = block->buttons.first; but; but = but->next) {
- if (but->dt != UI_EMBOSS_PULLDOWN) {
+ if (block->flag & UI_BLOCK_SHOW_SHORTCUT_ALWAYS) {
+ /* Skip icon-only buttons (as used in the toolbar). */
+ if (but->drawstr[0] == '\0') {
+ continue;
+ }
+ }
+ else if (but->dt != UI_EMBOSS_PULLDOWN) {
continue;
}
@@ -1230,6 +1211,18 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
}
}
+void ui_but_override_flag(uiBut *but)
+{
+ const int override_status = RNA_property_static_override_status(&but->rnapoin, but->rnaprop, but->rnaindex);
+
+ if (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN) {
+ but->flag |= UI_BUT_OVERRIDEN;
+ }
+ else {
+ but->flag &= ~UI_BUT_OVERRIDEN;
+ }
+}
+
void UI_block_update_from_old(const bContext *C, uiBlock *block)
{
uiBut *but_old;
@@ -1267,6 +1260,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
{
wmWindow *window = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
+ ARegion *region = CTX_wm_region(C);
uiBut *but;
BLI_assert(block->active);
@@ -1294,6 +1288,10 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
}
ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f);
+ ui_but_override_flag(but);
+ if (UI_but_is_decorator(but)) {
+ ui_but_anim_decorate_update_from_flag(but);
+ }
}
@@ -1302,12 +1300,12 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
if (block->layouts.first) {
UI_block_layout_resolve(block, NULL, NULL);
}
- ui_block_align_calc(block);
+ ui_block_align_calc(block, CTX_wm_region(C));
if ((block->flag & UI_BLOCK_LOOP) && (block->flag & UI_BLOCK_NUMSELECT)) {
ui_menu_block_set_keyaccels(block); /* could use a different flag to check */
}
- if (block->flag & UI_BLOCK_LOOP) {
+ if (block->flag & (UI_BLOCK_LOOP | UI_BLOCK_SHOW_SHORTCUT_ALWAYS)) {
ui_menu_block_set_keymaps(C, block);
}
@@ -1342,6 +1340,8 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
UI_block_align_end(block);
}
+ ui_update_flexible_spacing(region, block);
+
block->endblock = 1;
}
@@ -1388,7 +1388,6 @@ void UI_block_draw(const bContext *C, uiBlock *block)
ARegion *ar;
uiBut *but;
rcti rect;
- int multisample_enabled;
/* get menu region or area region */
ar = CTX_wm_menu(C);
@@ -1398,13 +1397,8 @@ void UI_block_draw(const bContext *C, uiBlock *block)
if (!block->endblock)
UI_block_end(C, block);
- /* disable AA, makes widgets too blurry */
- multisample_enabled = glIsEnabled(GL_MULTISAMPLE);
- if (multisample_enabled)
- glDisable(GL_MULTISAMPLE);
-
/* we set this only once */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
/* scale fonts */
ui_fontscale(&style.paneltitle.points, block->aspect);
@@ -1416,22 +1410,26 @@ void UI_block_draw(const bContext *C, uiBlock *block)
ui_but_to_pixelrect(&rect, ar, block, NULL);
/* pixel space for AA widgets */
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
+ gpuPushProjectionMatrix();
+ gpuPushMatrix();
+ gpuLoadIdentity();
wmOrtho2_region_pixelspace(ar);
/* back */
if (block->flag & UI_BLOCK_RADIAL)
ui_draw_pie_center(block);
+ else if (block->flag & UI_BLOCK_POPOVER)
+ ui_draw_popover_back(ar, &style, block, &rect);
else if (block->flag & UI_BLOCK_LOOP)
ui_draw_menu_back(&style, block, &rect);
else if (block->panel)
ui_draw_aligned_panel(&style, block, &rect, UI_panel_category_is_visible(ar));
+ BLF_batch_draw_begin();
+ UI_icon_draw_cache_begin();
+ UI_widgetbase_draw_cache_begin();
+
/* widgets */
for (but = block->buttons.first; but; but = but->next) {
if (!(but->flag & (UI_HIDDEN | UI_SCROLLED))) {
@@ -1444,16 +1442,47 @@ void UI_block_draw(const bContext *C, uiBlock *block)
}
}
- /* restore matrix */
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ UI_widgetbase_draw_cache_end();
+ UI_icon_draw_cache_end();
+ BLF_batch_draw_end();
- if (multisample_enabled)
- glEnable(GL_MULTISAMPLE);
+ /* restore matrix */
+ gpuPopProjectionMatrix();
+ gpuPopMatrix();
+}
+
+static void ui_block_message_subscribe(ARegion *ar, struct wmMsgBus *mbus, uiBlock *block)
+{
+ uiBut *but_prev = NULL;
+ /* possibly we should keep the region this block is contained in? */
+ for (uiBut *but = block->buttons.first; but; but = but->next) {
+ if (but->rnapoin.type && but->rnaprop) {
+ /* quick check to avoid adding buttons representing a vector, multiple times. */
+ if ((but_prev &&
+ (but_prev->rnaprop == but->rnaprop) &&
+ (but_prev->rnapoin.type == but->rnapoin.type) &&
+ (but_prev->rnapoin.data == but->rnapoin.data) &&
+ (but_prev->rnapoin.id.data == but->rnapoin.id.data)) == false)
+ {
+ /* TODO: could make this into utility function. */
+ WM_msg_subscribe_rna(
+ mbus, &but->rnapoin, but->rnaprop,
+ &(const wmMsgSubscribeValue){
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ }, __func__);
+ but_prev = but;
+ }
+ }
+ }
+}
- ui_draw_links(block);
+void UI_region_message_subscribe(ARegion *ar, struct wmMsgBus *mbus)
+{
+ for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
+ ui_block_message_subscribe(ar, mbus, block);
+ }
}
/* ************* EVENTS ************* */
@@ -1511,6 +1540,18 @@ int ui_but_is_pushed_ex(uiBut *but, double *value)
if (*value == (double)but->hardmax) is_push = true;
}
break;
+ case UI_BTYPE_TAB:
+ if (but->rnaprop && but->custom_data) {
+ /* uiBut.custom_data points to data this tab represents (e.g. workspace).
+ * uiBut.rnapoin/prop store an active value (e.g. active workspace). */
+ if (RNA_property_type(but->rnaprop) == PROP_POINTER) {
+ PointerRNA active_ptr = RNA_property_pointer_get(&but->rnapoin, but->rnaprop);
+ if (active_ptr.data == but->custom_data) {
+ is_push = true;
+ }
+ }
+ }
+ break;
default:
is_push = -1;
break;
@@ -1537,83 +1578,6 @@ static void ui_but_update_select_flag(uiBut *but, double *value)
}
}
-static uiBut *ui_linkline_find_inlink(uiBlock *block, void *poin)
-{
- uiBut *but;
-
- but = block->buttons.first;
- while (but) {
- if (but->type == UI_BTYPE_INLINK) {
- if (but->poin == poin) return but;
- }
- but = but->next;
- }
- return NULL;
-}
-
-static void ui_linkline_add(ListBase *listb, uiBut *but, uiBut *bt, short deactive)
-{
- uiLinkLine *line;
-
- line = MEM_callocN(sizeof(uiLinkLine), "linkline");
- BLI_addtail(listb, line);
- line->from = but;
- line->to = bt;
- line->deactive = deactive;
-}
-
-uiBut *UI_block_links_find_inlink(uiBlock *block, void *poin)
-{
- return ui_linkline_find_inlink(block, poin);
-}
-
-void UI_block_links_compose(uiBlock *block)
-{
- uiBut *but, *bt;
- uiLink *link;
- void ***ppoin;
- int a;
-
- but = block->buttons.first;
- while (but) {
- if (but->type == UI_BTYPE_LINK) {
- link = but->link;
-
- /* for all pointers in the array */
- if (link) {
- if (link->ppoin) {
- ppoin = link->ppoin;
- for (a = 0; a < *(link->totlink); a++) {
- bt = ui_linkline_find_inlink(block, (*ppoin)[a]);
- if (bt) {
- if ((but->flag & UI_BUT_SCA_LINK_GREY) || (bt->flag & UI_BUT_SCA_LINK_GREY)) {
- ui_linkline_add(&link->lines, but, bt, true);
- }
- else {
- ui_linkline_add(&link->lines, but, bt, false);
- }
-
- }
- }
- }
- else if (link->poin) {
- bt = ui_linkline_find_inlink(block, *link->poin);
- if (bt) {
- if ((but->flag & UI_BUT_SCA_LINK_GREY) || (bt->flag & UI_BUT_SCA_LINK_GREY)) {
- ui_linkline_add(&link->lines, but, bt, true);
- }
- else {
- ui_linkline_add(&link->lines, but, bt, false);
- }
- }
- }
- }
- }
- but = but->next;
- }
-}
-
-
/* ************************************************ */
void UI_block_lock_set(uiBlock *block, bool val, const char *lockstr)
@@ -1630,48 +1594,78 @@ void UI_block_lock_clear(uiBlock *block)
block->lockstr = NULL;
}
-/* *************************************************************** */
-
-void ui_linkline_remove(uiLinkLine *line, uiBut *but)
-{
- uiLink *link;
- int a, b;
-
- BLI_remlink(&but->link->lines, line);
-
- link = line->from->link;
-
- /* are there more pointers allowed? */
- if (link->ppoin) {
+/* *********************** data get/set ***********************
+ * this either works with the pointed to data, or can work with
+ * an edit override pointer while dragging for example */
- if (*(link->totlink) == 1) {
- *(link->totlink) = 0;
- MEM_freeN(*(link->ppoin));
- *(link->ppoin) = NULL;
- }
- else {
- b = 0;
- for (a = 0; a < (*(link->totlink)); a++) {
- if ((*(link->ppoin))[a] != line->to->poin) {
- (*(link->ppoin))[b] = (*(link->ppoin))[a];
- b++;
- }
- }
- (*(link->totlink))--;
+/* Get PointerRNA which will point to a data inside of an evaluated
+ * ID datablock.
+ */
+static PointerRNA ui_but_evaluated_rnapoin_get(uiBut *but)
+{
+ BLI_assert(but->rnaprop != NULL);
+ /* TODO(sergey): evil_C sounds.. EVIL! Any clear way to avoid this? */
+ PointerRNA rnapoin_eval = but->rnapoin;
+ /* If there is no animation or drivers, it doesn't matter if we read value
+ * from evaluated datablock or from original one.
+ *
+ * Reading from original one is much faster, since we don't need to do any
+ * PointerRNA remapping or hash lookup.
+ */
+ if (BKE_animdata_from_id(but->rnapoin.id.data) == NULL) {
+ return rnapoin_eval;
+ }
+ /* Same goes for the properties which can not be animated. */
+ if (!RNA_property_animateable(&but->rnapoin, but->rnaprop)) {
+ return rnapoin_eval;
+ }
+ Depsgraph *depsgraph = CTX_data_depsgraph(but->block->evil_C);
+ /* ID pointer we can always remap, they are inside of depsgraph. */
+ rnapoin_eval.id.data =
+ DEG_get_evaluated_id(depsgraph, rnapoin_eval.id.data);
+ /* Some of ID datablocks do not have their evaluated copy inside
+ * of dependency graph. If it's such datablock, no need to worry about
+ * data pointer.
+ */
+ if (rnapoin_eval.id.data == but->rnapoin.id.data) {
+ return rnapoin_eval;
+ }
+ /* For the data pointer it's getting a bit more involved, since it can
+ * whether be and ID, or can be a property deep inside of ID.
+ *
+ * We start from checking if it's an ID, since that is the less involved
+ * code path, and probably is executed in most of the cases.
+ */
+ if (but->rnapoin.data == but->rnapoin.id.data) {
+ rnapoin_eval.data = DEG_get_evaluated_id(depsgraph, rnapoin_eval.data);
+ return rnapoin_eval;
+ }
+ /* We aren't as lucky as we thought we are :(
+ *
+ * Since we don't know what the property is, we get it's RNA path
+ * relative to the original ID, and then we decent down from evaluated
+ * ID to the same property.
+ *
+ * This seems to be most straightforward way to get sub-data pointers
+ * which can be buried deep inside of ID block.
+ */
+ const char *rna_path =
+ RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
+ if (rna_path != NULL) {
+ PointerRNA id_ptr;
+ RNA_id_pointer_create(rnapoin_eval.id.data, &id_ptr);
+ if (!RNA_path_resolve_full(&id_ptr,
+ rna_path,
+ &rnapoin_eval,
+ NULL, NULL))
+ {
+ /* TODO(sergey): Anything to do here to recover? */
}
+ MEM_freeN((void *)rna_path);
}
- else {
- *(link->poin) = NULL;
- }
-
- MEM_freeN(line);
- //REDRAW
+ return rnapoin_eval;
}
-/* *********************** data get/set ***********************
- * this either works with the pointed to data, or can work with
- * an edit override pointer while dragging for example */
-
/* for buttons pointing to color for example */
void ui_but_v3_get(uiBut *but, float vec[3])
{
@@ -1687,16 +1681,18 @@ void ui_but_v3_get(uiBut *but, float vec[3])
zero_v3(vec);
+ PointerRNA rnapoin_eval = ui_but_evaluated_rnapoin_get(but);
+
if (RNA_property_type(prop) == PROP_FLOAT) {
- int tot = RNA_property_array_length(&but->rnapoin, prop);
+ int tot = RNA_property_array_length(&rnapoin_eval, prop);
BLI_assert(tot > 0);
if (tot == 3) {
- RNA_property_float_get_array(&but->rnapoin, prop, vec);
+ RNA_property_float_get_array(&rnapoin_eval, prop, vec);
}
else {
tot = min_ii(tot, 3);
for (a = 0; a < tot; a++) {
- vec[a] = RNA_property_float_get_index(&but->rnapoin, prop, a);
+ vec[a] = RNA_property_float_get_index(&rnapoin_eval, prop, a);
}
}
}
@@ -1876,27 +1872,29 @@ double ui_but_value_get(uiBut *but)
BLI_assert(but->rnaindex != -1);
+ PointerRNA rnapoin_eval = ui_but_evaluated_rnapoin_get(but);
+
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN:
if (RNA_property_array_check(prop))
- value = RNA_property_boolean_get_index(&but->rnapoin, prop, but->rnaindex);
+ value = RNA_property_boolean_get_index(&rnapoin_eval, prop, but->rnaindex);
else
- value = RNA_property_boolean_get(&but->rnapoin, prop);
+ value = RNA_property_boolean_get(&rnapoin_eval, prop);
break;
case PROP_INT:
if (RNA_property_array_check(prop))
- value = RNA_property_int_get_index(&but->rnapoin, prop, but->rnaindex);
+ value = RNA_property_int_get_index(&rnapoin_eval, prop, but->rnaindex);
else
- value = RNA_property_int_get(&but->rnapoin, prop);
+ value = RNA_property_int_get(&rnapoin_eval, prop);
break;
case PROP_FLOAT:
if (RNA_property_array_check(prop))
- value = RNA_property_float_get_index(&but->rnapoin, prop, but->rnaindex);
+ value = RNA_property_float_get_index(&rnapoin_eval, prop, but->rnaindex);
else
- value = RNA_property_float_get(&but->rnapoin, prop);
+ value = RNA_property_float_get(&rnapoin_eval, prop);
break;
case PROP_ENUM:
- value = RNA_property_enum_get(&but->rnapoin, prop);
+ value = RNA_property_enum_get(&rnapoin_eval, prop);
break;
default:
value = 0.0;
@@ -2039,7 +2037,7 @@ static bool ui_but_icon_extra_is_visible_text_clear(const uiBut *but)
static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but)
{
- BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
+ BLI_assert(ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_TAB));
return ((but->editstr == NULL) &&
(but->drawstr[0] != '\0') &&
(but->flag & UI_BUT_VALUE_CLEAR));
@@ -2082,6 +2080,11 @@ uiButExtraIconType ui_but_icon_extra_get(uiBut *but)
return UI_BUT_ICONEXTRA_EYEDROPPER;
}
break;
+ case UI_BTYPE_TAB:
+ if (ui_but_icon_extra_is_visible_search_unlink(but)) {
+ return UI_BUT_ICONEXTRA_CLEAR;
+ }
+ break;
default:
break;
}
@@ -2196,14 +2199,23 @@ void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int
*r_use_exp_float = false;
}
- if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
+ if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_TAB)) {
PropertyType type;
const char *buf = NULL;
int buf_len;
type = RNA_property_type(but->rnaprop);
- if (type == PROP_STRING) {
+ if ((but->type == UI_BTYPE_TAB) && (but->custom_data)) {
+ StructRNA *ptr_type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
+ PointerRNA ptr;
+
+ /* uiBut.custom_data points to data this tab represents (e.g. workspace).
+ * uiBut.rnapoin/prop store an active value (e.g. active workspace). */
+ RNA_pointer_create(but->rnapoin.id.data, ptr_type, but->custom_data, &ptr);
+ buf = RNA_struct_name_get_alloc(&ptr, str, maxlen, &buf_len);
+ }
+ else if (type == PROP_STRING) {
/* RNA string */
buf = RNA_property_string_get_alloc(&but->rnapoin, but->rnaprop, str, maxlen, &buf_len);
}
@@ -2239,12 +2251,7 @@ void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int
MEM_freeN((void *)buf);
}
}
- else if (but->type == UI_BTYPE_TEXT) {
- /* string */
- BLI_strncpy(str, but->poin, maxlen);
- return;
- }
- else if (but->type == UI_BTYPE_SEARCH_MENU) {
+ else if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
/* string */
BLI_strncpy(str, but->poin, maxlen);
return;
@@ -2443,7 +2450,7 @@ static void ui_but_string_free_internal(uiBut *but)
bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
{
- if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
+ if (but->rnaprop && but->rnapoin.data && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
if (RNA_property_editable(&but->rnapoin, but->rnaprop)) {
PropertyType type;
@@ -2455,17 +2462,15 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
return true;
}
else if (type == PROP_POINTER) {
- /* RNA pointer */
- PointerRNA ptr, rptr;
- PropertyRNA *prop;
-
if (str[0] == '\0') {
RNA_property_pointer_set(&but->rnapoin, but->rnaprop, PointerRNA_NULL);
return true;
}
else {
- ptr = but->rnasearchpoin;
- prop = but->rnasearchprop;
+ /* RNA pointer */
+ PointerRNA rptr;
+ PointerRNA ptr = but->rnasearchpoin;
+ PropertyRNA *prop = but->rnasearchprop;
if (prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr))
RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr);
@@ -2488,10 +2493,32 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
}
}
}
+ else if (but->type == UI_BTYPE_TAB) {
+ if (but->rnaprop && but->custom_data) {
+ StructRNA *ptr_type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ /* uiBut.custom_data points to data this tab represents (e.g. workspace).
+ * uiBut.rnapoin/prop store an active value (e.g. active workspace). */
+ RNA_pointer_create(but->rnapoin.id.data, ptr_type, but->custom_data, &ptr);
+ prop = RNA_struct_name_property(ptr_type);
+ if (RNA_property_editable(&ptr, prop)) {
+ RNA_property_string_set(&ptr, prop, str);
+ }
+ }
+ }
else if (but->type == UI_BTYPE_TEXT) {
/* string */
- if (ui_but_is_utf8(but)) BLI_strncpy_utf8(but->poin, str, but->hardmax);
- else BLI_strncpy(but->poin, str, but->hardmax);
+ if (!but->poin || (str[0] == '\0')) {
+ str = "";
+ }
+ else if (ui_but_is_utf8(but)) {
+ BLI_strncpy_utf8(but->poin, str, but->hardmax);
+ }
+ else {
+ BLI_strncpy(but->poin, str, but->hardmax);
+ }
return true;
}
@@ -2675,14 +2702,6 @@ static void ui_set_but_soft_range(uiBut *but)
/* ******************* Free ********************/
-static void ui_free_link(uiLink *link)
-{
- if (link) {
- BLI_freelistN(&link->lines);
- MEM_freeN(link);
- }
-}
-
/* can be called with C==NULL */
static void ui_but_free(const bContext *C, uiBut *but)
{
@@ -2703,6 +2722,10 @@ static void ui_but_free(const bContext *C, uiBut *but)
MEM_freeN(but->hold_argN);
}
+ if (!but->editstr && but->free_search_arg) {
+ MEM_SAFE_FREE(but->search_arg);
+ }
+
if (but->active) {
/* XXX solve later, buttons should be free-able without context ideally,
* however they may have open tooltips or popup windows, which need to
@@ -2719,7 +2742,6 @@ static void ui_but_free(const bContext *C, uiBut *but)
if (but->str && but->str != but->strdata) {
MEM_freeN(but->str);
}
- ui_free_link(but->link);
if ((but->type == UI_BTYPE_IMAGE) && but->poin) {
IMB_freeImBuf((struct ImBuf *)but->poin);
@@ -2761,6 +2783,27 @@ void UI_block_free(const bContext *C, uiBlock *block)
MEM_freeN(block);
}
+void UI_blocklist_update_window_matrix(const bContext *C, const ListBase *lb)
+{
+ ARegion *region = CTX_wm_region(C);
+ wmWindow *window = CTX_wm_window(C);
+
+ for (uiBlock *block = lb->first; block; block = block->next) {
+ if (block->active) {
+ ui_update_window_matrix(window, region, block);
+ }
+ }
+}
+
+void UI_blocklist_draw(const bContext *C, const ListBase *lb)
+{
+ for (uiBlock *block = lb->first; block; block = block->next) {
+ if (block->active) {
+ UI_block_draw(C, block);
+ }
+ }
+}
+
/* can be called with C==NULL */
void UI_blocklist_free(const bContext *C, ListBase *lb)
{
@@ -2817,7 +2860,6 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, sh
uiBlock *block;
wmWindow *window;
Scene *scn;
- int getsizex, getsizey;
window = CTX_wm_window(C);
scn = CTX_data_scene(C);
@@ -2847,33 +2889,18 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, sh
if (region)
UI_block_region_set(block, region);
- /* window matrix and aspect */
- if (region && region->swinid) {
- wm_subwindow_matrix_get(window, region->swinid, block->winmat);
- wm_subwindow_size_get(window, region->swinid, &getsizex, &getsizey);
-
- block->aspect = 2.0f / fabsf(getsizex * block->winmat[0][0]);
- }
- else {
- /* no subwindow created yet, for menus for example, so we
- * use the main window instead, since buttons are created
- * there anyway */
- wm_subwindow_matrix_get(window, window->screen->mainwin, block->winmat);
- wm_subwindow_size_get(window, window->screen->mainwin, &getsizex, &getsizey);
+ /* Set window matrix and aspect for region and OpenGL state. */
+ ui_update_window_matrix(window, region, block);
- block->aspect = 2.0f / fabsf(getsizex * block->winmat[0][0]);
+ /* Tag as popup menu if not created within a region. */
+ if (!(region && region->visible)) {
block->auto_open = true;
- block->flag |= UI_BLOCK_LOOP; /* tag as menu */
+ block->flag |= UI_BLOCK_LOOP;
}
return block;
}
-uiBlock *UI_block_find_in_region(const char *name, ARegion *ar)
-{
- return BLI_findstring(&ar->uiblocks, name, offsetof(uiBlock, name));
-}
-
void UI_block_emboss_set(uiBlock *block, char dt)
{
block->dt = dt;
@@ -3030,6 +3057,7 @@ void ui_but_update_ex(uiBut *but, const bool validate)
case UI_BTYPE_TEXT:
case UI_BTYPE_SEARCH_MENU:
+ case UI_BTYPE_TAB:
if (!but->editstr) {
char str[UI_MAX_DRAW_STR];
@@ -3153,6 +3181,16 @@ void ui_block_cm_to_display_space_range(uiBlock *block, float *min, float *max)
*max = max_fff(UNPACK3(pixel));
}
+static uiBut *ui_but_alloc(const eButType type)
+{
+ switch (type) {
+ case UI_BTYPE_TAB:
+ return MEM_callocN(sizeof(uiButTab), "uiButTab");
+ default:
+ return MEM_callocN(sizeof(uiBut), "uiBut");
+ }
+}
+
/**
* \brief ui_def_but is the function that draws many button types
*
@@ -3186,7 +3224,7 @@ static uiBut *ui_def_but(
}
}
- but = MEM_callocN(sizeof(uiBut), "uiBut");
+ but = ui_but_alloc(type & BUTTYPE);
but->type = type & BUTTYPE;
but->pointype = type & UI_BUT_POIN_TYPES;
@@ -3250,7 +3288,7 @@ static uiBut *ui_def_but(
ELEM(but->type,
UI_BTYPE_MENU, UI_BTYPE_TEXT, UI_BTYPE_LABEL,
UI_BTYPE_BLOCK, UI_BTYPE_BUT_MENU, UI_BTYPE_SEARCH_MENU,
- UI_BTYPE_PROGRESS_BAR))
+ UI_BTYPE_PROGRESS_BAR, UI_BTYPE_POPOVER))
{
but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
}
@@ -3273,7 +3311,8 @@ static uiBut *ui_def_but(
UI_BTYPE_BLOCK, UI_BTYPE_BUT, UI_BTYPE_LABEL,
UI_BTYPE_PULLDOWN, UI_BTYPE_ROUNDBOX, UI_BTYPE_LISTBOX,
UI_BTYPE_BUT_MENU, UI_BTYPE_SCROLL, UI_BTYPE_GRIP,
- UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE) ||
+ UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE,
+ UI_BTYPE_SEPR_SPACER) ||
(but->type >= UI_BTYPE_SEARCH_MENU))
{
/* pass */
@@ -3441,6 +3480,12 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu
block->flag |= UI_BLOCK_IS_FLIP;
}
+static void ui_but_submenu_enable(uiBlock *block, uiBut *but)
+{
+ but->flag |= UI_BUT_ICON_SUBMENU;
+ block->content_hints |= BLOCK_CONTAINS_SUBMENU_BUT;
+}
+
/**
* ui_def_but_rna_propname and ui_def_but_rna
* both take the same args except for propname vs prop, this is done so we can
@@ -3576,11 +3621,11 @@ static uiBut *ui_def_but_rna(
}
if ((type == UI_BTYPE_MENU) && (but->dt == UI_EMBOSS_PULLDOWN)) {
- but->flag |= UI_BUT_ICON_SUBMENU;
+ ui_but_submenu_enable(block, but);
}
const char *info;
- if (!RNA_property_editable_info(&but->rnapoin, prop, &info)) {
+ if (but->rnapoin.data && !RNA_property_editable_info(&but->rnapoin, prop, &info)) {
ui_def_but_rna__disable(but, info);
}
@@ -3999,19 +4044,6 @@ uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcon
/* END Button containing both string label and icon */
-void UI_but_link_set(uiBut *but, void **poin, void ***ppoin, short *tot, int from, int to)
-{
- uiLink *link;
-
- link = but->link = MEM_callocN(sizeof(uiLink), "new uilink");
-
- link->poin = poin;
- link->ppoin = ppoin;
- link->totlink = tot;
- link->fromcode = from;
- link->tocode = to;
-}
-
/* cruft to make uiBlock and uiBut private */
int UI_blocklist_min_y_get(ListBase *lb)
@@ -4328,7 +4360,7 @@ uiBut *uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, in
ui_def_but_icon(but, icon, UI_HAS_ICON);
but->drawflag |= UI_BUT_ICON_LEFT;
- but->flag |= UI_BUT_ICON_SUBMENU;
+ ui_but_submenu_enable(block, but);
but->menu_create_func = func;
ui_but_update(but);
@@ -4360,7 +4392,7 @@ uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg,
but->drawflag |= UI_BUT_ICON_LEFT;
}
but->flag |= UI_HAS_ICON;
- but->flag |= UI_BUT_ICON_SUBMENU;
+ ui_but_submenu_enable(block, but);
but->block_create_func = func;
ui_but_update(but);
@@ -4479,7 +4511,7 @@ static void operator_enum_search_cb(const struct bContext *C, void *but, const c
for (item = item_array; item->identifier; item++) {
/* note: need to give the index rather than the identifier because the enum can be freed */
if (BLI_strcasestr(item->name, str)) {
- if (false == UI_search_item_add(items, item->name, SET_INT_IN_POINTER(item->value), 0))
+ if (false == UI_search_item_add(items, item->name, SET_INT_IN_POINTER(item->value), item->icon))
break;
}
}
@@ -4610,7 +4642,7 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
tmp = BLI_strdup(RNA_property_identifier(but->rnaprop));
}
else if (type == BUT_GET_RNASTRUCT_IDENTIFIER) {
- if (but->rnaprop)
+ if (but->rnaprop && but->rnapoin.data)
tmp = BLI_strdup(RNA_struct_identifier(but->rnapoin.type));
else if (but->optype)
tmp = BLI_strdup(but->optype->idname);
@@ -4687,6 +4719,9 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
PointerRNA *opptr = UI_but_operator_ptr_get(but);
wmOperatorType *ot = but->optype;
+ /* so the context is passed to itemf functions */
+ WM_operator_properties_sanitize(opptr, false);
+
/* if the default property of the operator is enum and it is set,
* fetch the tooltip of the selected value so that "Snap" and "Mirror"
* operator menus in the Anim Editors will show tooltips for the different
diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c
index 36b0b938b5a..c945746c2df 100644
--- a/source/blender/editors/interface/interface_align.c
+++ b/source/blender/editors/interface/interface_align.c
@@ -110,9 +110,9 @@ enum {
bool ui_but_can_align(const uiBut *but)
{
- return (
- !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE) &&
- (BLI_rctf_size_x(&but->rect) > 0.0f) && (BLI_rctf_size_y(&but->rect) > 0.0f));
+ const bool btype_can_align = !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N,
+ UI_BTYPE_TAB, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER);
+ return (btype_can_align && (BLI_rctf_size_x(&but->rect) > 0.0f) && (BLI_rctf_size_y(&but->rect) > 0.0f));
}
/**
@@ -320,13 +320,43 @@ static int ui_block_align_butal_cmp(const void *a, const void *b)
return 0;
}
+static void ui_block_align_but_to_region(uiBut *but, const ARegion *region)
+{
+ rctf *rect = &but->rect;
+ const float but_width = BLI_rctf_size_x(rect);
+ const float but_height = BLI_rctf_size_y(rect);
+ const float px = U.pixelsize;
+
+ switch (but->drawflag & UI_BUT_ALIGN) {
+ case UI_BUT_ALIGN_TOP:
+ rect->ymax = region->winy + px;
+ rect->ymin = but->rect.ymax - but_height;
+ break;
+ case UI_BUT_ALIGN_DOWN:
+ rect->ymin = -px;
+ rect->ymax = rect->ymin + but_height;
+ break;
+ case UI_BUT_ALIGN_LEFT:
+ rect->xmin = -px;
+ rect->xmax = rect->xmin + but_width;
+ break;
+ case UI_BUT_ALIGN_RIGHT:
+ rect->xmax = region->winx + px;
+ rect->xmin = rect->xmax - but_width;
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+}
+
/**
* Compute the alignment of all 'align groups' of buttons in given block.
*
* This is using an order-independent algorithm, i.e. alignment of buttons should be OK regardless of order in which
* they are added to the block.
*/
-void ui_block_align_calc(uiBlock *block)
+void ui_block_align_calc(uiBlock *block, const ARegion *region)
{
uiBut *but;
int num_buttons = 0;
@@ -338,10 +368,17 @@ void ui_block_align_calc(uiBlock *block)
int side;
int i, j;
- /* First loop: we count number of buttons belonging to an align group, and clear their align flag. */
+ /* First loop: we count number of buttons belonging to an align group, and clear their align flag.
+ * Tabs get some special treatment here, they get aligned to region border. */
for (but = block->buttons.first; but; but = but->next) {
- /* Clear old align flags. */
- but->drawflag &= ~UI_BUT_ALIGN_ALL;
+ /* special case: tabs need to be aligned to a region border, drawflag tells which one */
+ if (but->type == UI_BTYPE_TAB) {
+ ui_block_align_but_to_region(but, region);
+ }
+ else {
+ /* Clear old align flags. */
+ but->drawflag &= ~UI_BUT_ALIGN_ALL;
+ }
if (but->alignnr != 0) {
num_buttons++;
@@ -462,7 +499,8 @@ void ui_block_align_calc(uiBlock *block)
bool ui_but_can_align(uiBut *but)
{
- return !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE);
+ return !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N,
+ UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER);
}
static bool buts_are_horiz(uiBut *but1, uiBut *but2)
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 10a23792e8f..cda70d405ad 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -39,12 +39,14 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_nla.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_keyframing.h"
#include "UI_interface.h"
@@ -101,6 +103,30 @@ void ui_but_anim_flag(uiBut *but, float cfra)
}
}
+void ui_but_anim_decorate_update_from_flag(uiBut *but)
+{
+ BLI_assert(UI_but_is_decorator(but) && but->prev);
+ int flag = but->prev->flag;
+ if (flag & UI_BUT_DRIVEN) {
+ but->icon = ICON_AUTO;
+ }
+ else if (flag & UI_BUT_ANIMATED_KEY) {
+ but->icon = ICON_SPACE2;
+ }
+ else if (flag & UI_BUT_ANIMATED) {
+ but->icon = ICON_SPACE3;
+ }
+ else if (flag & UI_BUT_OVERRIDEN) {
+ but->icon = ICON_LIBRARY_DATA_OVERRIDE;
+ }
+ else {
+ but->icon = ICON_DOT;
+ }
+
+ const int flag_copy = (UI_BUT_DISABLED | UI_BUT_INACTIVE);
+ but->flag = (but->flag & ~flag_copy) | (flag & flag_copy);
+}
+
/**
* \a str can be NULL to only perform check if \a but has an expression at all.
* \return if button has an expression.
@@ -212,7 +238,7 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str)
/* updates */
driver->flag |= DRIVER_FLAG_RECOMPILE;
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME, NULL);
ok = true;
}
@@ -240,10 +266,11 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
if (special) {
/* NLA Strip property */
if (IS_AUTOKEY_ON(scene)) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
ReportList *reports = CTX_wm_reports(C);
ToolSettings *ts = scene->toolsettings;
- insert_keyframe_direct(reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, 0);
+ insert_keyframe_direct(depsgraph, reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, 0);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
}
@@ -252,10 +279,11 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
* making it easier to set up corrective drivers
*/
if (IS_AUTOKEY_ON(scene)) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
ReportList *reports = CTX_wm_reports(C);
ToolSettings *ts = scene->toolsettings;
- insert_keyframe_direct(reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, INSERTKEY_DRIVER);
+ insert_keyframe_direct(depsgraph, reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, INSERTKEY_DRIVER);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
}
@@ -264,6 +292,7 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
/* TODO: this should probably respect the keyingset only option for anim */
if (autokeyframe_cfra_can_key(scene, id)) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
ReportList *reports = CTX_wm_reports(C);
ToolSettings *ts = scene->toolsettings;
short flag = ANIM_get_keyframing_flags(scene, 1);
@@ -274,7 +303,8 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
* because a button may control all items of an array at once.
* E.g., color wheels (see T42567). */
BLI_assert((fcu->array_index == but->rnaindex) || (but->rnaindex == -1));
- insert_keyframe(bmain, reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)),
+ insert_keyframe(bmain, depsgraph, reports, id, action,
+ ((fcu->grp) ? (fcu->grp->name) : (NULL)),
fcu->rna_path, but->rnaindex, cfra, ts->keyframe_type, flag);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
@@ -293,3 +323,38 @@ void ui_but_anim_paste_driver(bContext *C)
/* this operator calls UI_context_active_but_prop_get */
WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
}
+
+void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy))
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ uiBut *but = arg_but;
+ but = but->prev;
+
+ /* FIXME(campbell), swapping active pointer is weak. */
+ SWAP(struct uiHandleButtonData *, but->active, but->next->active);
+ wm->op_undo_depth++;
+
+ if (but->flag & UI_BUT_DRIVEN) {
+ /* pass */
+ /* TODO: report? */
+ }
+ else if (but->flag & UI_BUT_ANIMATED_KEY) {
+ PointerRNA props_ptr;
+ wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_delete_button", false);
+ WM_operator_properties_create_ptr(&props_ptr, ot);
+ RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_properties_free(&props_ptr);
+ }
+ else {
+ PointerRNA props_ptr;
+ wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_insert_button", false);
+ WM_operator_properties_create_ptr(&props_ptr, ot);
+ RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_properties_free(&props_ptr);
+ }
+
+ SWAP(struct uiHandleButtonData *, but->active, but->next->active);
+ wm->op_undo_depth--;
+}
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 0306139bac0..240649c8ab0 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -24,6 +24,8 @@
* Generic context popup menus.
*/
+#include <string.h>
+
#include "MEM_guardedalloc.h"
#include "DNA_scene_types.h"
@@ -214,6 +216,98 @@ static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but, NULL);
}
+static bool ui_but_is_user_menu_compatible(bContext *C, uiBut *but)
+{
+ return (but->optype ||
+ (but->rnaprop &&
+ (RNA_property_type(but->rnaprop) == PROP_BOOLEAN) &&
+ (WM_context_member_from_ptr(C, &but->rnapoin) != NULL)) ||
+ UI_but_menutype_get(but));
+}
+
+static bUserMenuItem *ui_but_user_menu_find(bContext *C, uiBut *but, bUserMenu *um)
+{
+ MenuType *mt = NULL;
+ if (but->optype) {
+ IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
+ return (bUserMenuItem *)ED_screen_user_menu_item_find_operator(
+ &um->items, but->optype, prop, but->opcontext);
+ }
+ else if (but->rnaprop) {
+ const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin);
+ const char *prop_id = RNA_property_identifier(but->rnaprop);
+ return (bUserMenuItem *)ED_screen_user_menu_item_find_prop(
+ &um->items, member_id, prop_id, but->rnaindex);
+ }
+ else if ((mt = UI_but_menutype_get(but))) {
+ return (bUserMenuItem *)ED_screen_user_menu_item_find_menu(
+ &um->items, mt);
+ }
+ else {
+ return NULL;
+ }
+}
+
+static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um)
+{
+ BLI_assert(ui_but_is_user_menu_compatible(C, but));
+
+ char drawstr[sizeof(but->drawstr)];
+ STRNCPY(drawstr, but->drawstr);
+ if (but->flag & UI_BUT_HAS_SEP_CHAR) {
+ char *sep = strrchr(drawstr, UI_SEP_CHAR);
+ if (sep) {
+ *sep = '\0';
+ }
+ }
+
+ MenuType *mt = NULL;
+ if (but->optype) {
+ ED_screen_user_menu_item_add_operator(
+ &um->items, drawstr,
+ but->optype, but->opptr ? but->opptr->data : NULL, but->opcontext);
+ }
+ else if (but->rnaprop) {
+ /* Note: 'member_id' may be a path. */
+ const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin);
+ const char *data_path = RNA_path_from_ID_to_struct(&but->rnapoin);
+ const char *member_id_data_path = member_id;
+ if (data_path) {
+ member_id_data_path = BLI_sprintfN("%s.%s", member_id, data_path);
+ }
+ const char *prop_id = RNA_property_identifier(but->rnaprop);
+ /* Note, ignore 'drawstr', use property idname always. */
+ ED_screen_user_menu_item_add_prop(
+ &um->items, "",
+ member_id_data_path, prop_id, but->rnaindex);
+ if (data_path) {
+ MEM_freeN((void *)data_path);
+ }
+ if (member_id != member_id_data_path) {
+ MEM_freeN((void *)member_id_data_path);
+ }
+ }
+ else if ((mt = UI_but_menutype_get(but))) {
+ ED_screen_user_menu_item_add_menu(
+ &um->items, drawstr,
+ mt);
+ }
+}
+
+static void popup_user_menu_add_or_replace_func(bContext *C, void *arg1, void *UNUSED(arg2))
+{
+ uiBut *but = arg1;
+ bUserMenu *um = ED_screen_user_menu_ensure(C);
+ ui_but_user_menu_add(C, but, um);
+}
+
+static void popup_user_menu_remove_func(bContext *UNUSED(C), void *arg1, void *arg2)
+{
+ bUserMenu *um = arg1;
+ bUserMenuItem *umi = arg2;
+ ED_screen_user_menu_item_remove(&um->items, umi);
+}
+
static void ui_but_menu_add_path_operators(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop)
{
const PropertySubType subtype = RNA_property_subtype(prop);
@@ -285,6 +379,9 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
const bool is_array = RNA_property_array_length(&but->rnapoin, but->rnaprop) != 0;
const bool is_array_component = (is_array && but->rnaindex != -1);
+ const int override_status = RNA_property_static_override_status(ptr, prop, -1);
+ const bool is_overridable = (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0;
+
/* Keyframes */
if (but->flag & UI_BUT_ANIMATED_KEY) {
/* Set the (button_pointer, button_prop) and pointer data for Python access to the hovered ui element. */
@@ -378,6 +475,12 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
ICON_NONE, "ANIM_OT_paste_driver_button");
}
+
+ uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Edit Driver"),
+ ICON_DRIVER, "ANIM_OT_driver_button_edit");
+
+ uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"),
+ ICON_NONE, "SCREEN_OT_drivers_editor_show");
}
else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) {
/* pass */
@@ -385,23 +488,16 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
else if (is_anim) {
uiItemS(layout);
- if (is_array_component) {
- uiItemMenuEnumO(
- layout, C, "ANIM_OT_driver_button_add", "mapping_type",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Drivers"),
- ICON_DRIVER);
- }
- else {
- uiItemMenuEnumO(
- layout, C, "ANIM_OT_driver_button_add", "mapping_type",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"),
- ICON_DRIVER);
- }
+ uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"),
+ ICON_DRIVER, "ANIM_OT_driver_button_add");
if (ANIM_driver_can_paste()) {
uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
ICON_NONE, "ANIM_OT_paste_driver_button");
}
+
+ uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"),
+ ICON_NONE, "SCREEN_OT_drivers_editor_show");
}
/* Keying Sets */
@@ -428,6 +524,65 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
}
}
+ if (is_overridable) {
+ wmOperatorType *ot;
+ PointerRNA op_ptr;
+ /* Override Operators */
+ uiItemS(layout);
+
+ if (but->flag & UI_BUT_OVERRIDEN) {
+ if (is_array_component) {
+#if 0 /* Disabled for now. */
+ ot = WM_operatortype_find("UI_OT_override_type_set_button", false);
+ uiItemFullO_ptr(
+ layout, ot, "Overrides Type", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", true);
+ uiItemFullO_ptr(
+ layout, ot, "Single Override Type", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
+#endif
+ uiItemBooleanO(
+ layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Overrides"),
+ ICON_X, "UI_OT_override_remove_button", "all", true);
+ uiItemBooleanO(
+ layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Single Override"),
+ ICON_X, "UI_OT_override_remove_button", "all", false);
+ }
+ else {
+#if 0 /* Disabled for now. */
+ uiItemFullO(
+ layout, "UI_OT_override_type_set_button", "Override Type", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
+#endif
+ uiItemBooleanO(
+ layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Override"),
+ ICON_X, "UI_OT_override_remove_button", "all", true);
+ }
+ }
+ else {
+ if (is_array_component) {
+ ot = WM_operatortype_find("UI_OT_override_type_set_button", false);
+ uiItemFullO_ptr(
+ layout, ot, "Define Overrides", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", true);
+ uiItemFullO_ptr(
+ layout, ot, "Define Single Override", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
+ }
+ else {
+ uiItemFullO(
+ layout, "UI_OT_override_type_set_button", "Define Override", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
+ }
+ }
+ }
+
uiItemS(layout);
/* Property Operators */
@@ -532,6 +687,33 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
uiItemS(layout);
}
+ /* Favorites Menu */
+ if (ui_but_is_user_menu_compatible(C, but)) {
+ uiBlock *block = uiLayoutGetBlock(layout);
+ const int w = uiLayoutGetWidth(layout);
+ uiBut *but2;
+
+ but2 = uiDefIconTextBut(
+ block, UI_BTYPE_BUT, 0, ICON_MENU_PANEL,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Favorites Menu"),
+ 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0,
+ "Add to a user defined context menu (stored in the user preferences)");
+ UI_but_func_set(but2, popup_user_menu_add_or_replace_func, but, NULL);
+
+ bUserMenu *um = ED_screen_user_menu_find(C);
+ if (um) {
+ bUserMenuItem *umi = ui_but_user_menu_find(C, but, um);
+ if (umi != NULL) {
+ but2 = uiDefIconTextBut(
+ block, UI_BTYPE_BUT, 0, ICON_CANCEL,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Favorites Menu"),
+ 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ UI_but_func_set(but2, popup_user_menu_remove_func, um, umi);
+ }
+ }
+ uiItemS(layout);
+ }
+
/* Show header tools for header buttons. */
if (ui_block_is_menu(but->block) == false) {
ARegion *ar = CTX_wm_region(C);
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 50cd1c544c4..0a8a6d1f832 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -50,19 +50,22 @@
#include "IMB_imbuf_types.h"
#include "IMB_colormanagement.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "BLF_api.h"
-#include "GPU_draw.h"
-#include "GPU_basic_shader.h"
+#include "GPU_batch.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "UI_interface.h"
/* own include */
#include "interface_intern.h"
+
static int roundboxtype = UI_CNR_ALL;
void UI_draw_roundbox_corner_set(int type)
@@ -71,340 +74,564 @@ void UI_draw_roundbox_corner_set(int type)
* if this is undone, it's not that big a deal, only makes curves edges
* square for the */
roundboxtype = type;
-
}
+#if 0 /* unused */
int UI_draw_roundbox_corner_get(void)
{
return roundboxtype;
}
+#endif
+
+void UI_draw_roundbox_3ubAlpha(bool filled, float minx, float miny, float maxx, float maxy, float rad, const unsigned char col[3], unsigned char alpha)
+{
+ float colv[4];
+ colv[0] = ((float)col[0]) / 255;
+ colv[1] = ((float)col[1]) / 255;
+ colv[2] = ((float)col[2]) / 255;
+ colv[3] = ((float)alpha) / 255;
+ UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv);
+}
+
+void UI_draw_roundbox_3fvAlpha(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[3], float alpha)
+{
+ float colv[4];
+ colv[0] = col[0];
+ colv[1] = col[1];
+ colv[2] = col[2];
+ colv[3] = alpha;
+ UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv);
+}
-void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad)
+void UI_draw_roundbox_aa(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4])
{
+ uiWidgetBaseParameters widget_params = {
+ .recti.xmin = minx, .recti.ymin = miny,
+ .recti.xmax = maxx, .recti.ymax = maxy,
+ .radi = rad,
+ .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
+ .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
+ .color_inner1[0] = color[0], .color_inner2[0] = color[0],
+ .color_inner1[1] = color[1], .color_inner2[1] = color[1],
+ .color_inner1[2] = color[2], .color_inner2[2] = color[2],
+ .color_inner1[3] = color[3], .color_inner2[3] = color[3],
+ .alpha_discard = 1.0f,
+ };
+
+ GPU_blend(true);
+
+ if (filled) {
+ /* plain antialiased filled box */
+ widget_params.color_inner1[3] *= 0.125f;
+ widget_params.color_inner2[3] *= 0.125f;
+
+ /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space.
+ * If it has been scaled, then it's no longer valid. */
+ Gwn_Batch *batch = ui_batch_roundbox_get(filled, true);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GWN_batch_draw(batch);
+ }
+ else {
+ /* plain antialiased unfilled box */
+ GPU_line_smooth(true);
+
+ Gwn_Batch *batch = ui_batch_roundbox_get(filled, false);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GWN_batch_draw(batch);
+
+ GPU_line_smooth(false);
+ }
+
+ GPU_blend(false);
+}
+
+void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4])
+{
+#if 0
float vec[7][2] = {
{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
{0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805},
};
int a;
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
/* mult */
for (a = 0; a < 7; a++) {
mul_v2_fl(vec[a], rad);
}
- glBegin(mode);
+ uint vert_len = 0;
+ vert_len += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
+ vert_len += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
+ vert_len += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
+ vert_len += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(col);
+
+ immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_len);
/* start with corner right-bottom */
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
- glVertex2f(maxx - rad, miny);
+ immVertex2f(pos, maxx - rad, miny);
for (a = 0; a < 7; a++) {
- glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
+ immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
}
- glVertex2f(maxx, miny + rad);
+ immVertex2f(pos, maxx, miny + rad);
}
else {
- glVertex2f(maxx, miny);
+ immVertex2f(pos, maxx, miny);
}
/* corner right-top */
if (roundboxtype & UI_CNR_TOP_RIGHT) {
- glVertex2f(maxx, maxy - rad);
+ immVertex2f(pos, maxx, maxy - rad);
for (a = 0; a < 7; a++) {
- glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
+ immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
}
- glVertex2f(maxx - rad, maxy);
+ immVertex2f(pos, maxx - rad, maxy);
}
else {
- glVertex2f(maxx, maxy);
+ immVertex2f(pos, maxx, maxy);
}
/* corner left-top */
if (roundboxtype & UI_CNR_TOP_LEFT) {
- glVertex2f(minx + rad, maxy);
+ immVertex2f(pos, minx + rad, maxy);
for (a = 0; a < 7; a++) {
- glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
+ immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
}
- glVertex2f(minx, maxy - rad);
+ immVertex2f(pos, minx, maxy - rad);
}
else {
- glVertex2f(minx, maxy);
+ immVertex2f(pos, minx, maxy);
}
/* corner left-bottom */
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
- glVertex2f(minx, miny + rad);
+ immVertex2f(pos, minx, miny + rad);
for (a = 0; a < 7; a++) {
- glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
+ immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
}
- glVertex2f(minx + rad, miny);
+ immVertex2f(pos, minx + rad, miny);
}
else {
- glVertex2f(minx, miny);
+ immVertex2f(pos, minx, miny);
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
+#endif
+
+ uiWidgetBaseParameters widget_params = {
+ .recti.xmin = minx, .recti.ymin = miny,
+ .recti.xmax = maxx, .recti.ymax = maxy,
+ .radi = rad,
+ .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
+ .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
+ .color_inner1[0] = col[0], .color_inner2[0] = col[0],
+ .color_inner1[1] = col[1], .color_inner2[1] = col[1],
+ .color_inner1[2] = col[2], .color_inner2[2] = col[2],
+ .color_inner1[3] = col[3], .color_inner2[3] = col[3],
+ .alpha_discard = 1.0f,
+ };
+
+ Gwn_Batch *batch = ui_batch_roundbox_get(filled, false);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GWN_batch_draw(batch);
}
-static void round_box_shade_col(const float col1[3], float const col2[3], const float fac)
+#if 0
+static void round_box_shade_col(unsigned attrib, const float col1[3], float const col2[3], const float fac)
{
- float col[3] = {
+ float col[4] = {
fac * col1[0] + (1.0f - fac) * col2[0],
fac * col1[1] + (1.0f - fac) * col2[1],
- fac * col1[2] + (1.0f - fac) * col2[2]
+ fac * col1[2] + (1.0f - fac) * col2[2],
+ 1.0f
};
- glColor3fv(col);
+ immAttrib4fv(attrib, col);
}
+#endif
/* linear horizontal shade within button or in outline */
/* view2d scrollers use it */
void UI_draw_roundbox_shade_x(
- int mode, float minx, float miny, float maxx, float maxy,
- float rad, float shadetop, float shadedown)
+ bool filled, float minx, float miny, float maxx, float maxy,
+ float rad, float shadetop, float shadedown, const float col[4])
{
+#if 0
float vec[7][2] = {
{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
- {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
+ {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805},
+ };
const float div = maxy - miny;
const float idiv = 1.0f / div;
- float coltop[3], coldown[3], color[4];
+ float coltop[3], coldown[3];
+ int vert_count = 0;
int a;
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
/* mult */
for (a = 0; a < 7; a++) {
mul_v2_fl(vec[a], rad);
}
- /* get current color, needs to be outside of glBegin/End */
- glGetFloatv(GL_CURRENT_COLOR, color);
/* 'shade' defines strength of shading */
- coltop[0] = min_ff(1.0f, color[0] + shadetop);
- coltop[1] = min_ff(1.0f, color[1] + shadetop);
- coltop[2] = min_ff(1.0f, color[2] + shadetop);
- coldown[0] = max_ff(0.0f, color[0] + shadedown);
- coldown[1] = max_ff(0.0f, color[1] + shadedown);
- coldown[2] = max_ff(0.0f, color[2] + shadedown);
+ coltop[0] = min_ff(1.0f, col[0] + shadetop);
+ coltop[1] = min_ff(1.0f, col[1] + shadetop);
+ coltop[2] = min_ff(1.0f, col[2] + shadetop);
+ coldown[0] = max_ff(0.0f, col[0] + shadedown);
+ coldown[1] = max_ff(0.0f, col[1] + shadedown);
+ coldown[2] = max_ff(0.0f, col[2] + shadedown);
+
+ vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
- glBegin(mode);
+ immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_count);
/* start with corner right-bottom */
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
- round_box_shade_col(coltop, coldown, 0.0);
- glVertex2f(maxx - rad, miny);
+ round_box_shade_col(color, coltop, coldown, 0.0);
+ immVertex2f(pos, maxx - rad, miny);
for (a = 0; a < 7; a++) {
- round_box_shade_col(coltop, coldown, vec[a][1] * idiv);
- glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
+ round_box_shade_col(color, coltop, coldown, vec[a][1] * idiv);
+ immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
}
- round_box_shade_col(coltop, coldown, rad * idiv);
- glVertex2f(maxx, miny + rad);
+ round_box_shade_col(color, coltop, coldown, rad * idiv);
+ immVertex2f(pos, maxx, miny + rad);
}
else {
- round_box_shade_col(coltop, coldown, 0.0);
- glVertex2f(maxx, miny);
+ round_box_shade_col(color, coltop, coldown, 0.0);
+ immVertex2f(pos, maxx, miny);
}
/* corner right-top */
if (roundboxtype & UI_CNR_TOP_RIGHT) {
- round_box_shade_col(coltop, coldown, (div - rad) * idiv);
- glVertex2f(maxx, maxy - rad);
+ round_box_shade_col(color, coltop, coldown, (div - rad) * idiv);
+ immVertex2f(pos, maxx, maxy - rad);
for (a = 0; a < 7; a++) {
- round_box_shade_col(coltop, coldown, (div - rad + vec[a][1]) * idiv);
- glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
+ round_box_shade_col(color, coltop, coldown, (div - rad + vec[a][1]) * idiv);
+ immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
}
- round_box_shade_col(coltop, coldown, 1.0);
- glVertex2f(maxx - rad, maxy);
+ round_box_shade_col(color, coltop, coldown, 1.0);
+ immVertex2f(pos, maxx - rad, maxy);
}
else {
- round_box_shade_col(coltop, coldown, 1.0);
- glVertex2f(maxx, maxy);
+ round_box_shade_col(color, coltop, coldown, 1.0);
+ immVertex2f(pos, maxx, maxy);
}
/* corner left-top */
if (roundboxtype & UI_CNR_TOP_LEFT) {
- round_box_shade_col(coltop, coldown, 1.0);
- glVertex2f(minx + rad, maxy);
+ round_box_shade_col(color, coltop, coldown, 1.0);
+ immVertex2f(pos, minx + rad, maxy);
for (a = 0; a < 7; a++) {
- round_box_shade_col(coltop, coldown, (div - vec[a][1]) * idiv);
- glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
+ round_box_shade_col(color, coltop, coldown, (div - vec[a][1]) * idiv);
+ immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
}
- round_box_shade_col(coltop, coldown, (div - rad) * idiv);
- glVertex2f(minx, maxy - rad);
+ round_box_shade_col(color, coltop, coldown, (div - rad) * idiv);
+ immVertex2f(pos, minx, maxy - rad);
}
else {
- round_box_shade_col(coltop, coldown, 1.0);
- glVertex2f(minx, maxy);
+ round_box_shade_col(color, coltop, coldown, 1.0);
+ immVertex2f(pos, minx, maxy);
}
/* corner left-bottom */
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
- round_box_shade_col(coltop, coldown, rad * idiv);
- glVertex2f(minx, miny + rad);
+ round_box_shade_col(color, coltop, coldown, rad * idiv);
+ immVertex2f(pos, minx, miny + rad);
for (a = 0; a < 7; a++) {
- round_box_shade_col(coltop, coldown, (rad - vec[a][1]) * idiv);
- glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
+ round_box_shade_col(color, coltop, coldown, (rad - vec[a][1]) * idiv);
+ immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
}
- round_box_shade_col(coltop, coldown, 0.0);
- glVertex2f(minx + rad, miny);
+ round_box_shade_col(color, coltop, coldown, 0.0);
+ immVertex2f(pos, minx + rad, miny);
}
else {
- round_box_shade_col(coltop, coldown, 0.0);
- glVertex2f(minx, miny);
+ round_box_shade_col(color, coltop, coldown, 0.0);
+ immVertex2f(pos, minx, miny);
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
+#endif
+
+ uiWidgetBaseParameters widget_params = {
+ .recti.xmin = minx, .recti.ymin = miny,
+ .recti.xmax = maxx, .recti.ymax = maxy,
+ .radi = rad,
+ .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
+ .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
+ .color_inner1[0] = min_ff(1.0f, col[0] + shadetop),
+ .color_inner2[0] = max_ff(0.0f, col[0] + shadedown),
+ .color_inner1[1] = min_ff(1.0f, col[1] + shadetop),
+ .color_inner2[1] = max_ff(0.0f, col[1] + shadedown),
+ .color_inner1[2] = min_ff(1.0f, col[2] + shadetop),
+ .color_inner2[2] = max_ff(0.0f, col[2] + shadedown),
+ .color_inner1[3] = 1.0f,
+ .color_inner2[3] = 1.0f,
+ .alpha_discard = 1.0f,
+ };
+
+ Gwn_Batch *batch = ui_batch_roundbox_get(filled, false);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
+ GWN_batch_draw(batch);
}
+#if 0 /* unused */
/* linear vertical shade within button or in outline */
/* view2d scrollers use it */
void UI_draw_roundbox_shade_y(
- int mode, float minx, float miny, float maxx, float maxy,
- float rad, float shadeLeft, float shadeRight)
+ bool filled, float minx, float miny, float maxx, float maxy,
+ float rad, float shadeleft, float shaderight, const float col[4])
{
float vec[7][2] = {
{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
- {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
+ {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805},
+ };
const float div = maxx - minx;
const float idiv = 1.0f / div;
- float colLeft[3], colRight[3], color[4];
+ float colLeft[3], colRight[3];
+ int vert_count = 0;
int a;
/* mult */
for (a = 0; a < 7; a++) {
mul_v2_fl(vec[a], rad);
}
- /* get current color, needs to be outside of glBegin/End */
- glGetFloatv(GL_CURRENT_COLOR, color);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
/* 'shade' defines strength of shading */
- colLeft[0] = min_ff(1.0f, color[0] + shadeLeft);
- colLeft[1] = min_ff(1.0f, color[1] + shadeLeft);
- colLeft[2] = min_ff(1.0f, color[2] + shadeLeft);
- colRight[0] = max_ff(0.0f, color[0] + shadeRight);
- colRight[1] = max_ff(0.0f, color[1] + shadeRight);
- colRight[2] = max_ff(0.0f, color[2] + shadeRight);
+ colLeft[0] = min_ff(1.0f, col[0] + shadeleft);
+ colLeft[1] = min_ff(1.0f, col[1] + shadeleft);
+ colLeft[2] = min_ff(1.0f, col[2] + shadeleft);
+ colRight[0] = max_ff(0.0f, col[0] + shaderight);
+ colRight[1] = max_ff(0.0f, col[1] + shaderight);
+ colRight[2] = max_ff(0.0f, col[2] + shaderight);
+
- glBegin(mode);
+ vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
+
+ immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_count);
/* start with corner right-bottom */
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
- round_box_shade_col(colLeft, colRight, 0.0);
- glVertex2f(maxx - rad, miny);
+ round_box_shade_col(color, colLeft, colRight, 0.0);
+ immVertex2f(pos, maxx - rad, miny);
for (a = 0; a < 7; a++) {
- round_box_shade_col(colLeft, colRight, vec[a][0] * idiv);
- glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
+ round_box_shade_col(color, colLeft, colRight, vec[a][0] * idiv);
+ immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
}
- round_box_shade_col(colLeft, colRight, rad * idiv);
- glVertex2f(maxx, miny + rad);
+ round_box_shade_col(color, colLeft, colRight, rad * idiv);
+ immVertex2f(pos, maxx, miny + rad);
}
else {
- round_box_shade_col(colLeft, colRight, 0.0);
- glVertex2f(maxx, miny);
+ round_box_shade_col(color, colLeft, colRight, 0.0);
+ immVertex2f(pos, maxx, miny);
}
/* corner right-top */
if (roundboxtype & UI_CNR_TOP_RIGHT) {
- round_box_shade_col(colLeft, colRight, 0.0);
- glVertex2f(maxx, maxy - rad);
+ round_box_shade_col(color, colLeft, colRight, 0.0);
+ immVertex2f(pos, maxx, maxy - rad);
for (a = 0; a < 7; a++) {
- round_box_shade_col(colLeft, colRight, (div - rad - vec[a][0]) * idiv);
- glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
+ round_box_shade_col(color, colLeft, colRight, (div - rad - vec[a][0]) * idiv);
+ immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
}
- round_box_shade_col(colLeft, colRight, (div - rad) * idiv);
- glVertex2f(maxx - rad, maxy);
+ round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv);
+ immVertex2f(pos, maxx - rad, maxy);
}
else {
- round_box_shade_col(colLeft, colRight, 0.0);
- glVertex2f(maxx, maxy);
+ round_box_shade_col(color, colLeft, colRight, 0.0);
+ immVertex2f(pos, maxx, maxy);
}
/* corner left-top */
if (roundboxtype & UI_CNR_TOP_LEFT) {
- round_box_shade_col(colLeft, colRight, (div - rad) * idiv);
- glVertex2f(minx + rad, maxy);
+ round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv);
+ immVertex2f(pos, minx + rad, maxy);
for (a = 0; a < 7; a++) {
- round_box_shade_col(colLeft, colRight, (div - rad + vec[a][0]) * idiv);
- glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
+ round_box_shade_col(color, colLeft, colRight, (div - rad + vec[a][0]) * idiv);
+ immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
}
- round_box_shade_col(colLeft, colRight, 1.0);
- glVertex2f(minx, maxy - rad);
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx, maxy - rad);
}
else {
- round_box_shade_col(colLeft, colRight, 1.0);
- glVertex2f(minx, maxy);
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx, maxy);
}
/* corner left-bottom */
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
- round_box_shade_col(colLeft, colRight, 1.0);
- glVertex2f(minx, miny + rad);
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx, miny + rad);
for (a = 0; a < 7; a++) {
- round_box_shade_col(colLeft, colRight, (vec[a][0]) * idiv);
- glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
+ round_box_shade_col(color, colLeft, colRight, (vec[a][0]) * idiv);
+ immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
}
- round_box_shade_col(colLeft, colRight, 1.0);
- glVertex2f(minx + rad, miny);
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx + rad, miny);
}
else {
- round_box_shade_col(colLeft, colRight, 1.0);
- glVertex2f(minx, miny);
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx, miny);
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
+#endif /* unused */
-/* plain antialiased unfilled rectangle */
-void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad)
+void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4])
{
- float color[4];
-
- if (roundboxtype & UI_RB_ALPHA) {
- glGetFloatv(GL_CURRENT_COLOR, color);
- color[3] = 0.5;
- glColor4fv(color);
- glEnable(GL_BLEND);
- }
+ int ofs_y = 4 * U.pixelsize;
- /* set antialias line */
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ immRecti(pos, pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize));
+ immUnbindProgram();
}
-/* (old, used in outliner) plain antialiased filled box */
-void UI_draw_roundbox(float minx, float miny, float maxx, float maxy, float rad)
-{
- ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA);
-}
+/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
-void UI_draw_text_underline(int pos_x, int pos_y, int len, int height)
+/* based on UI_draw_roundbox_gl_mode, check on making a version which allows us to skip some sides */
+void ui_draw_but_TAB_outline(const rcti *rect, float rad, unsigned char highlight[3], unsigned char highlight_fade[3])
{
- int ofs_y = 4 * U.pixelsize;
- glRecti(pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize));
-}
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ /* add a 1px offset, looks nicer */
+ const int minx = rect->xmin + U.pixelsize, maxx = rect->xmax - U.pixelsize;
+ const int miny = rect->ymin + U.pixelsize, maxy = rect->ymax - U.pixelsize;
+ int a;
+ float vec[4][2] = {
+ {0.195, 0.02},
+ {0.55, 0.169},
+ {0.831, 0.45},
+ {0.98, 0.805},
+ };
-/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
+
+ /* mult */
+ for (a = 0; a < 4; a++) {
+ mul_v2_fl(vec[a], rad);
+ }
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ immBeginAtMost(GWN_PRIM_LINE_STRIP, 25);
+
+ immAttrib3ubv(col, highlight);
+
+ /* start with corner left-top */
+ if (roundboxtype & UI_CNR_TOP_LEFT) {
+ immVertex2f(pos, minx, maxy - rad);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, minx + vec[a][1], maxy - rad + vec[a][0]);
+ }
+ immVertex2f(pos, minx + rad, maxy);
+ }
+ else {
+ immVertex2f(pos, minx, maxy);
+ }
+
+ /* corner right-top */
+ if (roundboxtype & UI_CNR_TOP_RIGHT) {
+ immVertex2f(pos, maxx - rad, maxy);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, maxx - rad + vec[a][0], maxy - vec[a][1]);
+ }
+ immVertex2f(pos, maxx, maxy - rad);
+ }
+ else {
+ immVertex2f(pos, maxx, maxy);
+ }
+
+ immAttrib3ubv(col, highlight_fade);
+
+ /* corner right-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
+ immVertex2f(pos, maxx, miny + rad);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, maxx - vec[a][1], miny + rad - vec[a][0]);
+ }
+ immVertex2f(pos, maxx - rad, miny);
+ }
+ else {
+ immVertex2f(pos, maxx, miny);
+ }
+
+ /* corner left-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
+ immVertex2f(pos, minx + rad, miny);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, minx + rad - vec[a][0], miny + vec[a][1]);
+ }
+ immVertex2f(pos, minx, miny + rad);
+ }
+ else {
+ immVertex2f(pos, minx, miny);
+ }
+
+ immAttrib3ubv(col, highlight);
+
+ /* back to corner left-top */
+ immVertex2f(pos, minx, roundboxtype & UI_CNR_TOP_LEFT ? maxy - rad : maxy);
+
+ immEnd();
+ immUnbindProgram();
+}
void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
{
@@ -416,37 +643,37 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
if (!ibuf) return;
+ float facx = 1.0f;
+ float facy = 1.0f;
+
int w = BLI_rcti_size_x(rect);
int h = BLI_rcti_size_y(rect);
/* scissor doesn't seem to be doing the right thing...? */
#if 0
- //glColor4f(1.0, 0.f, 0.f, 1.f);
- //fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax)
-
/* prevent drawing outside widget area */
- GLint scissor[4];
- glGetIntegerv(GL_SCISSOR_BOX, scissor);
- glScissor(ar->winrct.xmin + rect->xmin, ar->winrct.ymin + rect->ymin, w, h);
+ int scissor[4];
+ GPU_scissor_get_i(scissor);
+ GPU_scissor(rect->xmin, rect->ymin, w, h);
#endif
- glEnable(GL_BLEND);
- glColor4f(0.0, 0.0, 0.0, 0.0);
+ GPU_blend(true);
if (w != ibuf->x || h != ibuf->y) {
- float facx = (float)w / (float)ibuf->x;
- float facy = (float)h / (float)ibuf->y;
- glPixelZoom(facx, facy);
+ facx = (float)w / (float)ibuf->x;
+ facy = (float)h / (float)ibuf->y;
}
- glaDrawPixelsAuto((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect);
- glPixelZoom(1.0f, 1.0f);
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(
+ &state, (float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect,
+ facx, facy, NULL);
- glDisable(GL_BLEND);
+ GPU_blend(false);
#if 0
// restore scissortest
- glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
#endif
#endif
@@ -455,43 +682,34 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
/**
* Draw title and text safe areas.
*
- * The first 4 parameters are the offsets for the view, not the zones.
+ * \Note This functionn is to be used with the 2D dashed shader enabled.
+ *
+ * \param pos is a PRIM_FLOAT, 2, GWN_FETCH_FLOAT vertex attrib
+ * \param line_origin is a PRIM_FLOAT, 2, GWN_FETCH_FLOAT vertex attrib
+ *
+ * The next 4 parameters are the offsets for the view, not the zones.
*/
void UI_draw_safe_areas(
- float x1, float x2, float y1, float y2,
+ uint pos, float x1, float x2, float y1, float y2,
const float title_aspect[2], const float action_aspect[2])
{
const float size_x_half = (x2 - x1) * 0.5f;
const float size_y_half = (y2 - y1) * 0.5f;
const float *safe_areas[] = {title_aspect, action_aspect};
- int safe_len = ARRAY_SIZE(safe_areas);
- bool is_first = true;
+ const int safe_len = ARRAY_SIZE(safe_areas);
for (int i = 0; i < safe_len; i++) {
if (safe_areas[i][0] || safe_areas[i][1]) {
- float margin_x, margin_y;
- float minx, miny, maxx, maxy;
-
- if (is_first) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
- is_first = false;
- }
-
- margin_x = safe_areas[i][0] * size_x_half;
- margin_y = safe_areas[i][1] * size_y_half;
+ float margin_x = safe_areas[i][0] * size_x_half;
+ float margin_y = safe_areas[i][1] * size_y_half;
- minx = x1 + margin_x;
- miny = y1 + margin_y;
- maxx = x2 - margin_x;
- maxy = y2 - margin_y;
+ float minx = x1 + margin_x;
+ float miny = y1 + margin_y;
+ float maxx = x2 - margin_x;
+ float maxy = y2 - margin_y;
- glBegin(GL_LINE_LOOP);
- glVertex2f(maxx, miny);
- glVertex2f(maxx, maxy);
- glVertex2f(minx, maxy);
- glVertex2f(minx, miny);
- glEnd();
+ imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
}
}
}
@@ -500,65 +718,73 @@ void UI_draw_safe_areas(
static void draw_scope_end(const rctf *rect, GLint *scissor)
{
/* restore scissortest */
- glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
/* outline */
- glColor4f(0.f, 0.f, 0.f, 0.5f);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.5f};
+ UI_draw_roundbox_4fv(false, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f, color);
}
static void histogram_draw_one(
float r, float g, float b, float alpha,
- float x, float y, float w, float h, const float *data, int res, const bool is_line)
+ float x, float y, float w, float h, const float *data, int res, const bool is_line,
+ unsigned int pos_attrib)
{
- glEnable(GL_LINE_SMOOTH);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- glColor4f(r, g, b, alpha);
+ float color[4] = {r, g, b, alpha};
+
+ /* that can happen */
+ if (res == 0)
+ return;
+
+ GPU_line_smooth(true);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
+
+ immUniformColor4fv(color);
if (is_line) {
/* curve outline */
- glLineWidth(1.5);
+ GPU_line_width(1.5);
- glBegin(GL_LINE_STRIP);
+ immBegin(GWN_PRIM_LINE_STRIP, res);
for (int i = 0; i < res; i++) {
float x2 = x + i * (w / (float)res);
- glVertex2f(x2, y + (data[i] * h));
+ immVertex2f(pos_attrib, x2, y + (data[i] * h));
}
- glEnd();
+ immEnd();
}
else {
/* under the curve */
- glBegin(GL_TRIANGLE_STRIP);
- glVertex2f(x, y);
- glVertex2f(x, y + (data[0] * h));
+ immBegin(GWN_PRIM_TRI_STRIP, res * 2);
+ immVertex2f(pos_attrib, x, y);
+ immVertex2f(pos_attrib, x, y + (data[0] * h));
for (int i = 1; i < res; i++) {
float x2 = x + i * (w / (float)res);
- glVertex2f(x2, y + (data[i] * h));
- glVertex2f(x2, y);
+ immVertex2f(pos_attrib, x2, y + (data[i] * h));
+ immVertex2f(pos_attrib, x2, y);
}
- glEnd();
+ immEnd();
/* curve outline */
- glColor4f(0.f, 0.f, 0.f, 0.25f);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.25f);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glBegin(GL_LINE_STRIP);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ immBegin(GWN_PRIM_LINE_STRIP, res);
for (int i = 0; i < res; i++) {
float x2 = x + i * (w / (float)res);
- glVertex2f(x2, y + (data[i] * h));
+ immVertex2f(pos_attrib, x2, y + (data[i] * h));
}
- glEnd();
+ immEnd();
}
- glDisable(GL_LINE_SMOOTH);
+ GPU_line_smooth(false);
}
#define HISTOGRAM_TOT_GRID_LINES 4
-void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
+void ui_draw_but_HISTOGRAM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
{
Histogram *hist = (Histogram *)but->poin;
int res = hist->x_resolution;
@@ -574,60 +800,95 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol)
float w = BLI_rctf_size_x(&rect);
float h = BLI_rctf_size_y(&rect) * hist->ymax;
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- UI_ThemeColor4(TH_PREVIEW_BACK);
+ float color[4];
+ UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
/* need scissor test, histogram can draw outside of boundary */
- GLint scissor[4];
- glGetIntegerv(GL_VIEWPORT, scissor);
- glScissor(ar->winrct.xmin + (rect.xmin - 1),
- ar->winrct.ymin + (rect.ymin - 1),
- (rect.xmax + 1) - (rect.xmin - 1),
- (rect.ymax + 1) - (rect.ymin - 1));
-
- glColor4f(1.f, 1.f, 1.f, 0.08f);
+ int scissor[4];
+ GPU_scissor_get_i(scissor);
+ GPU_scissor(
+ (rect.xmin - 1),
+ (rect.ymin - 1),
+ (rect.xmax + 1) - (rect.xmin - 1),
+ (rect.ymax + 1) - (rect.ymin - 1));
+
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
/* draw grid lines here */
for (int i = 1; i <= HISTOGRAM_TOT_GRID_LINES; i++) {
const float fac = (float)i / (float)HISTOGRAM_TOT_GRID_LINES;
/* so we can tell the 1.0 color point */
if (i == HISTOGRAM_TOT_GRID_LINES) {
- glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
}
- fdrawline(rect.xmin, rect.ymin + fac * h, rect.xmax, rect.ymin + fac * h);
- fdrawline(rect.xmin + fac * w, rect.ymin, rect.xmin + fac * w, rect.ymax);
+ immBegin(GWN_PRIM_LINES, 4);
+
+ immVertex2f(pos, rect.xmin, rect.ymin + fac * h);
+ immVertex2f(pos, rect.xmax, rect.ymin + fac * h);
+
+ immVertex2f(pos, rect.xmin + fac * w, rect.ymin);
+ immVertex2f(pos, rect.xmin + fac * w, rect.ymax);
+
+ immEnd();
}
if (hist->mode == HISTO_MODE_LUMA) {
- histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line);
+ histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line, pos);
}
else if (hist->mode == HISTO_MODE_ALPHA) {
- histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line);
+ histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line, pos);
}
else {
if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_R)
- histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line);
+ histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line, pos);
if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_G)
- histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line);
+ histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line, pos);
if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_B)
- histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line);
+ histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line, pos);
}
+ immUnbindProgram();
+
/* outline */
draw_scope_end(&rect, scissor);
}
#undef HISTOGRAM_TOT_GRID_LINES
-void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
+static void waveform_draw_one(float *waveform, int nbr, const float col[3])
+{
+ Gwn_VertFormat format = {0};
+ uint pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, nbr);
+
+ GWN_vertbuf_attr_fill(vbo, pos_id, waveform);
+
+ /* TODO store the Gwn_Batch inside the scope */
+ Gwn_Batch *batch = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
+ GWN_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f);
+ GWN_batch_draw(batch);
+
+ GWN_batch_discard(batch);
+}
+
+void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
{
Scopes *scopes = (Scopes *)but->poin;
- GLint scissor[4];
+ int scissor[4];
float colors[3][3];
float colorsycc[3][3] = {{1, 0, 1}, {1, 1, 0}, {0, 1, 1}};
float colors_alpha[3][3], colorsycc_alpha[3][3]; /* colors pre multiplied by alpha for speed up */
@@ -646,7 +907,7 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
scopes->wavefrm_yfac = 0.98f;
float w = BLI_rctf_size_x(&rect) - 7;
float h = BLI_rctf_size_y(&rect) * scopes->wavefrm_yfac;
- float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) / 2.0f;
+ float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) * 0.5f;
float w3 = w / 3.0f;
/* log scale for alpha */
@@ -661,108 +922,141 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
}
}
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ /* Flush text cache before changing scissors. */
+ BLF_batch_draw_flush();
- UI_ThemeColor4(TH_PREVIEW_BACK);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ float color[4];
+ UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
/* need scissor test, waveform can draw outside of boundary */
- glGetIntegerv(GL_VIEWPORT, scissor);
- glScissor(ar->winrct.xmin + (rect.xmin - 1),
- ar->winrct.ymin + (rect.ymin - 1),
- (rect.xmax + 1) - (rect.xmin - 1),
- (rect.ymax + 1) - (rect.ymin - 1));
-
- glColor4f(1.f, 1.f, 1.f, 0.08f);
- /* draw grid lines here */
+ GPU_scissor_get_i(scissor);
+ GPU_scissor(
+ (rect.xmin - 1),
+ (rect.ymin - 1),
+ (rect.xmax + 1) - (rect.xmin - 1),
+ (rect.ymax + 1) - (rect.ymin - 1));
+
+ /* draw scale numbers first before binding any shader */
for (int i = 0; i < 6; i++) {
char str[4];
BLI_snprintf(str, sizeof(str), "%-3d", i * 20);
str[3] = '\0';
- fdrawline(rect.xmin + 22, yofs + (i / 5.f) * h, rect.xmax + 1, yofs + (i / 5.f) * h);
- BLF_draw_default(rect.xmin + 1, yofs - 5 + (i / 5.f) * h, 0, str, sizeof(str) - 1);
- /* in the loop because blf_draw reset it */
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ BLF_color4f(BLF_default(), 1.0f, 1.0f, 1.0f, 0.08f);
+ BLF_draw_default(rect.xmin + 1, yofs - 5 + (i * 0.2f) * h, 0, str, sizeof(str) - 1);
}
+
+ /* Flush text cache before drawing things on top. */
+ BLF_batch_draw_flush();
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
+
+ /* draw grid lines here */
+ immBegin(GWN_PRIM_LINES, 12);
+
+ for (int i = 0; i < 6; i++) {
+ immVertex2f(pos, rect.xmin + 22, yofs + (i * 0.2f) * h);
+ immVertex2f(pos, rect.xmax + 1, yofs + (i * 0.2f) * h);
+ }
+
+ immEnd();
+
/* 3 vertical separation */
if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) {
+ immBegin(GWN_PRIM_LINES, 4);
+
for (int i = 1; i < 3; i++) {
- fdrawline(rect.xmin + i * w3, rect.ymin, rect.xmin + i * w3, rect.ymax);
+ immVertex2f(pos, rect.xmin + i * w3, rect.ymin);
+ immVertex2f(pos, rect.xmin + i * w3, rect.ymax);
}
+
+ immEnd();
}
/* separate min max zone on the right */
- fdrawline(rect.xmin + w, rect.ymin, rect.xmin + w, rect.ymax);
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, rect.xmin + w, rect.ymin);
+ immVertex2f(pos, rect.xmin + w, rect.ymax);
+ immEnd();
+
/* 16-235-240 level in case of ITU-R BT601/709 */
- glColor4f(1.f, 0.4f, 0.f, 0.2f);
+ immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709)) {
- fdrawline(rect.xmin + 22, yofs + h * 16.0f / 255.0f, rect.xmax + 1, yofs + h * 16.0f / 255.0f);
- fdrawline(rect.xmin + 22, yofs + h * 235.0f / 255.0f, rect.xmin + w3, yofs + h * 235.0f / 255.0f);
- fdrawline(rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f, rect.xmax + 1, yofs + h * 235.0f / 255.0f);
- fdrawline(rect.xmin + w3, yofs + h * 240.0f / 255.0f, rect.xmax + 1, yofs + h * 240.0f / 255.0f);
+ immBegin(GWN_PRIM_LINES, 8);
+
+ immVertex2f(pos, rect.xmin + 22, yofs + h * 16.0f / 255.0f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 16.0f / 255.0f);
+
+ immVertex2f(pos, rect.xmin + 22, yofs + h * 235.0f / 255.0f);
+ immVertex2f(pos, rect.xmin + w3, yofs + h * 235.0f / 255.0f);
+
+ immVertex2f(pos, rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 235.0f / 255.0f);
+
+ immVertex2f(pos, rect.xmin + w3, yofs + h * 240.0f / 255.0f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 240.0f / 255.0f);
+
+ immEnd();
}
/* 7.5 IRE black point level for NTSC */
- if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA)
- fdrawline(rect.xmin, yofs + h * 0.075f, rect.xmax + 1, yofs + h * 0.075f);
+ if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, rect.xmin, yofs + h * 0.075f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 0.075f);
+ immEnd();
+ }
if (scopes->ok && scopes->waveform_1 != NULL) {
-
- /* LUMA (1 channel) */
glBlendFunc(GL_ONE, GL_ONE);
- glColor3f(alpha, alpha, alpha);
- glPointSize(1.0);
+ GPU_point_size(1.0);
+ /* LUMA (1 channel) */
if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
+ float col[3] = {alpha, alpha, alpha};
- glBlendFunc(GL_ONE, GL_ONE);
-
- glPushMatrix();
- glEnableClientState(GL_VERTEX_ARRAY);
+ gpuPushMatrix();
+ gpuTranslate2f(rect.xmin, yofs);
+ gpuScale2f(w, h);
- glTranslatef(rect.xmin, yofs, 0.f);
- glScalef(w, h, 0.f);
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
+ waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, col);
- glDisableClientState(GL_VERTEX_ARRAY);
- glPopMatrix();
+ gpuPopMatrix();
/* min max */
- glColor3f(0.5f, 0.5f, 0.5f);
+ immUniformColor3f(0.5f, 0.5f, 0.5f);
min = yofs + scopes->minmax[0][0] * h;
max = yofs + scopes->minmax[0][1] * h;
CLAMP(min, rect.ymin, rect.ymax);
CLAMP(max, rect.ymin, rect.ymax);
- fdrawline(rect.xmax - 3, min, rect.xmax - 3, max);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, rect.xmax - 3, min);
+ immVertex2f(pos, rect.xmax - 3, max);
+ immEnd();
}
/* RGB (3 channel) */
else if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) {
- glBlendFunc(GL_ONE, GL_ONE);
+ gpuPushMatrix();
+ gpuTranslate2f(rect.xmin, yofs);
+ gpuScale2f(w, h);
- glEnableClientState(GL_VERTEX_ARRAY);
+ waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, colors_alpha[0]);
+ waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, colors_alpha[1]);
+ waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, colors_alpha[2]);
- glPushMatrix();
-
- glTranslatef(rect.xmin, yofs, 0.f);
- glScalef(w, h, 0.f);
-
- glColor3fv( colors_alpha[0] );
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
-
- glColor3fv( colors_alpha[1] );
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
-
- glColor3fv( colors_alpha[2] );
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
-
- glDisableClientState(GL_VERTEX_ARRAY);
- glPopMatrix();
+ gpuPopMatrix();
}
/* PARADE / YCC (3 channels) */
else if (ELEM(scopes->wavefrm_mode,
@@ -774,49 +1068,47 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
{
int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB_PARADE);
- glBlendFunc(GL_ONE, GL_ONE);
-
- glPushMatrix();
- glEnableClientState(GL_VERTEX_ARRAY);
+ gpuPushMatrix();
+ gpuTranslate2f(rect.xmin, yofs);
+ gpuScale2f(w3, h);
- glTranslatef(rect.xmin, yofs, 0.f);
- glScalef(w3, h, 0.f);
+ waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, (rgb) ? colors_alpha[0] : colorsycc_alpha[0]);
- glColor3fv((rgb) ? colors_alpha[0] : colorsycc_alpha[0]);
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
+ gpuTranslate2f(1.0f, 0.0f);
+ waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, (rgb) ? colors_alpha[1] : colorsycc_alpha[1]);
- glTranslatef(1.f, 0.f, 0.f);
- glColor3fv((rgb) ? colors_alpha[1] : colorsycc_alpha[1]);
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
+ gpuTranslate2f(1.0f, 0.0f);
+ waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, (rgb) ? colors_alpha[2] : colorsycc_alpha[2]);
- glTranslatef(1.f, 0.f, 0.f);
- glColor3fv((rgb) ? colors_alpha[2] : colorsycc_alpha[2]);
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
-
- glDisableClientState(GL_VERTEX_ARRAY);
- glPopMatrix();
+ gpuPopMatrix();
}
+
/* min max */
if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA ) {
for (int c = 0; c < 3; c++) {
if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_RGB_PARADE, SCOPES_WAVEFRM_RGB))
- glColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f);
+ immUniformColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f);
else
- glColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f);
+ immUniformColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f);
min = yofs + scopes->minmax[c][0] * h;
max = yofs + scopes->minmax[c][1] * h;
CLAMP(min, rect.ymin, rect.ymax);
CLAMP(max, rect.ymin, rect.ymax);
- fdrawline(rect.xmin + w + 2 + c * 2, min, rect.xmin + w + 2 + c * 2, max);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, rect.xmin + w + 2 + c * 2, min);
+ immVertex2f(pos, rect.xmin + w + 2 + c * 2, max);
+ immEnd();
}
}
}
+ immUnbindProgram();
+
/* outline */
draw_scope_end(&rect, scissor);
+
+ GPU_blend(false);
}
static float polar_to_x(float center, float diam, float ampli, float angle)
@@ -829,10 +1121,10 @@ static float polar_to_y(float center, float diam, float ampli, float angle)
return center + diam * ampli * sinf(angle);
}
-static void vectorscope_draw_target(float centerx, float centery, float diam, const float colf[3])
+static void vectorscope_draw_target(unsigned int pos, float centerx, float centery, float diam, const float colf[3])
{
float y, u, v;
- float tangle = 0.f, tampli;
+ float tangle = 0.0f, tampli;
float dangle, dampli, dangle2, dampli2;
rgb_to_yuv(colf[0], colf[1], colf[2], &y, &u, &v, BLI_YUV_ITU_BT709);
@@ -844,44 +1136,44 @@ static void vectorscope_draw_target(float centerx, float centery, float diam, co
tampli = sqrtf(u * u + v * v);
/* small target vary by 2.5 degree and 2.5 IRE unit */
- glColor4f(1.0f, 1.0f, 1.0, 0.12f);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f);
dangle = DEG2RADF(2.5f);
dampli = 2.5f / 200.0f;
- glBegin(GL_LINE_LOOP);
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
- glEnd();
+ immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
+ immEnd();
/* big target vary by 10 degree and 20% amplitude */
- glColor4f(1.0f, 1.0f, 1.0, 0.12f);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f);
dangle = DEG2RADF(10.0f);
dampli = 0.2f * tampli;
dangle2 = DEG2RADF(5.0f);
dampli2 = 0.5f * dampli;
- glBegin(GL_LINE_STRIP);
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2));
- glEnd();
- glBegin(GL_LINE_STRIP);
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2));
- glEnd();
- glBegin(GL_LINE_STRIP);
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2));
- glEnd();
- glBegin(GL_LINE_STRIP);
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2));
- glEnd();
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2));
+ immEnd();
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2));
+ immEnd();
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2));
+ immEnd();
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2));
+ immEnd();
}
-void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
+void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
{
const float skin_rad = DEG2RADF(123.0f); /* angle in radians of the skin tone line */
Scopes *scopes = (Scopes *)but->poin;
@@ -899,114 +1191,132 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
float w = BLI_rctf_size_x(&rect);
float h = BLI_rctf_size_y(&rect);
- float centerx = rect.xmin + w / 2;
- float centery = rect.ymin + h / 2;
+ float centerx = rect.xmin + w * 0.5f;
+ float centery = rect.ymin + h * 0.5f;
float diam = (w < h) ? w : h;
float alpha = scopes->vecscope_alpha * scopes->vecscope_alpha * scopes->vecscope_alpha;
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- UI_ThemeColor4(TH_PREVIEW_BACK);
+ float color[4];
+ UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
/* need scissor test, hvectorscope can draw outside of boundary */
- GLint scissor[4];
- glGetIntegerv(GL_VIEWPORT, scissor);
- glScissor(ar->winrct.xmin + (rect.xmin - 1),
- ar->winrct.ymin + (rect.ymin - 1),
- (rect.xmax + 1) - (rect.xmin - 1),
- (rect.ymax + 1) - (rect.ymin - 1));
-
- glColor4f(1.f, 1.f, 1.f, 0.08f);
+ int scissor[4];
+ GPU_scissor_get_i(scissor);
+ GPU_scissor(
+ (rect.xmin - 1),
+ (rect.ymin - 1),
+ (rect.xmax + 1) - (rect.xmin - 1),
+ (rect.ymax + 1) - (rect.ymin - 1));
+
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
/* draw grid elements */
/* cross */
- fdrawline(centerx - (diam / 2) - 5, centery, centerx + (diam / 2) + 5, centery);
- fdrawline(centerx, centery - (diam / 2) - 5, centerx, centery + (diam / 2) + 5);
+ immBegin(GWN_PRIM_LINES, 4);
+
+ immVertex2f(pos, centerx - (diam * 0.5f) - 5, centery);
+ immVertex2f(pos, centerx + (diam * 0.5f) + 5, centery);
+
+ immVertex2f(pos, centerx, centery - (diam * 0.5f) - 5);
+ immVertex2f(pos, centerx, centery + (diam * 0.5f) + 5);
+
+ immEnd();
+
/* circles */
for (int j = 0; j < 5; j++) {
- glBegin(GL_LINE_LOOP);
const int increment = 15;
+ immBegin(GWN_PRIM_LINE_LOOP, (int)(360 / increment));
for (int i = 0; i <= 360 - increment; i += increment) {
const float a = DEG2RADF((float)i);
- const float r = (j + 1) / 10.0f;
- glVertex2f(polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a));
+ const float r = (j + 1) * 0.1f;
+ immVertex2f(pos, polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a));
}
- glEnd();
+ immEnd();
}
/* skin tone line */
- glColor4f(1.f, 0.4f, 0.f, 0.2f);
- fdrawline(polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5, skin_rad),
- polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1, skin_rad));
+ immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5f, skin_rad));
+ immVertex2f(pos, polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1f, skin_rad));
+ immEnd();
+
/* saturation points */
for (int i = 0; i < 6; i++)
- vectorscope_draw_target(centerx, centery, diam, colors[i]);
+ vectorscope_draw_target(pos, centerx, centery, diam, colors[i]);
if (scopes->ok && scopes->vecscope != NULL) {
/* pixel point cloud */
- glBlendFunc(GL_ONE, GL_ONE);
- glColor3f(alpha, alpha, alpha);
+ float col[3] = {alpha, alpha, alpha};
- glPushMatrix();
- glEnableClientState(GL_VERTEX_ARRAY);
+ glBlendFunc(GL_ONE, GL_ONE);
+ GPU_point_size(1.0);
- glTranslatef(centerx, centery, 0.f);
- glScalef(diam, diam, 0.f);
+ gpuPushMatrix();
+ gpuTranslate2f(centerx, centery);
+ gpuScaleUniform(diam);
- glVertexPointer(2, GL_FLOAT, 0, scopes->vecscope);
- glPointSize(1.0);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
+ waveform_draw_one(scopes->vecscope, scopes->waveform_tot, col);
- glDisableClientState(GL_VERTEX_ARRAY);
- glPopMatrix();
+ gpuPopMatrix();
}
+ immUnbindProgram();
+
/* outline */
draw_scope_end(&rect, scissor);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
-static void ui_draw_colorband_handle_tri_hlight(float x1, float y1, float halfwidth, float height)
+static void ui_draw_colorband_handle_tri_hlight(unsigned int pos, float x1, float y1, float halfwidth, float height)
{
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_smooth(true);
- glBegin(GL_LINE_STRIP);
- glVertex2f(x1 + halfwidth, y1);
- glVertex2f(x1, y1 + height);
- glVertex2f(x1 - halfwidth, y1);
- glEnd();
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos, x1 + halfwidth, y1);
+ immVertex2f(pos, x1, y1 + height);
+ immVertex2f(pos, x1 - halfwidth, y1);
+ immEnd();
- glDisable(GL_LINE_SMOOTH);
+ GPU_line_smooth(false);
}
-static void ui_draw_colorband_handle_tri(float x1, float y1, float halfwidth, float height, bool fill)
+static void ui_draw_colorband_handle_tri(unsigned int pos, float x1, float y1, float halfwidth, float height, bool fill)
{
glEnable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH);
- glBegin(fill ? GL_TRIANGLES : GL_LINE_LOOP);
- glVertex2f(x1 + halfwidth, y1);
- glVertex2f(x1, y1 + height);
- glVertex2f(x1 - halfwidth, y1);
- glEnd();
+ immBegin(fill ? GWN_PRIM_TRIS : GWN_PRIM_LINE_LOOP, 3);
+ immVertex2f(pos, x1 + halfwidth, y1);
+ immVertex2f(pos, x1, y1 + height);
+ immVertex2f(pos, x1 - halfwidth, y1);
+ immEnd();
glDisable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH);
}
-static void ui_draw_colorband_handle_box(float x1, float y1, float x2, float y2, bool fill)
+static void ui_draw_colorband_handle_box(unsigned int pos, float x1, float y1, float x2, float y2, bool fill)
{
- glBegin(fill ? GL_QUADS : GL_LINE_LOOP);
- glVertex2f(x1, y1);
- glVertex2f(x1, y2);
- glVertex2f(x2, y2);
- glVertex2f(x2, y1);
- glEnd();
+ immBegin(fill ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, 4);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x2, y1);
+ immEnd();
}
static void ui_draw_colorband_handle(
- const rcti *rect, float x,
+ uint shdr_pos, const rcti *rect, float x,
const float rgb[3], struct ColorManagedDisplay *display,
bool active)
{
@@ -1025,18 +1335,26 @@ static void ui_draw_colorband_handle(
y1 = floorf(y1 + 0.5f);
if (active || half_width < min_width) {
- glBegin(GL_LINES);
- glColor3ub(0, 0, 0);
- glVertex2f(x, y1);
- glVertex2f(x, y2);
- glEnd();
- setlinestyle(active ? 2 : 1);
- glBegin(GL_LINES);
- glColor3ub(200, 200, 200);
- glVertex2f(x, y1);
- glVertex2f(x, y2);
- glEnd();
- setlinestyle(0);
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("colors_len", 2); /* "advanced" mode */
+ immUniformArray4fv("colors", (float *)(float[][4]){{0.8f, 0.8f, 0.8f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
+ immUniform1f("dash_width", active ? 4.0f : 2.0f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(shdr_pos, x, y1);
+ immVertex2f(shdr_pos, x, y2);
+ immEnd();
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* hide handles when zoomed out too far */
if (half_width < min_width) {
@@ -1047,45 +1365,46 @@ static void ui_draw_colorband_handle(
/* shift handle down */
y1 -= half_width;
- glColor3ub(0, 0, 0);
- ui_draw_colorband_handle_box(x - half_width, y1 - 1, x + half_width, y1 + height, false);
+ immUniformColor3ub(0, 0, 0);
+ ui_draw_colorband_handle_box(shdr_pos, x - half_width, y1 - 1, x + half_width, y1 + height, false);
/* draw all triangles blended */
- glEnable(GL_BLEND);
+ GPU_blend(true);
- ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true);
+ ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true);
if (active)
- glColor3ub(196, 196, 196);
+ immUniformColor3ub(196, 196, 196);
else
- glColor3ub(96, 96, 96);
- ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true);
+ immUniformColor3ub(96, 96, 96);
+ ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true);
if (active)
- glColor3ub(255, 255, 255);
+ immUniformColor3ub(255, 255, 255);
else
- glColor3ub(128, 128, 128);
- ui_draw_colorband_handle_tri_hlight(x, y1 + height - 1, (half_width - 1), (half_width - 1));
+ immUniformColor3ub(128, 128, 128);
+ ui_draw_colorband_handle_tri_hlight(shdr_pos, x, y1 + height - 1, (half_width - 1), (half_width - 1));
- glColor3ub(0, 0, 0);
- ui_draw_colorband_handle_tri_hlight(x, y1 + height, half_width, half_width);
+ immUniformColor3ub(0, 0, 0);
+ ui_draw_colorband_handle_tri_hlight(shdr_pos, x, y1 + height, half_width, half_width);
- glDisable(GL_BLEND);
+ GPU_blend(false);
- glColor3ub(128, 128, 128);
- ui_draw_colorband_handle_box(x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true);
+ immUniformColor3ub(128, 128, 128);
+ ui_draw_colorband_handle_box(shdr_pos, x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true);
if (display) {
IMB_colormanagement_scene_linear_to_display_v3(colf, display);
}
- glColor3fv(colf);
- ui_draw_colorband_handle_box(x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true);
+ immUniformColor3fv(colf);
+ ui_draw_colorband_handle_box(shdr_pos, x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true);
}
void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
{
struct ColorManagedDisplay *display = NULL;
+ uint pos_id, col_id;
ColorBand *coba = (ColorBand *)(but->editcoba ? but->editcoba : but->poin);
if (coba == NULL) return;
@@ -1096,23 +1415,28 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
float x1 = rect->xmin;
float sizex = rect->xmax - x1;
float sizey = BLI_rcti_size_y(rect);
- float sizey_solid = sizey / 4;
+ float sizey_solid = sizey * 0.25f;
float y1 = rect->ymin;
- /* Drawing the checkerboard.
- * This could be optimized with a single checkerboard shader,
- * instead of drawing twice and using stippling the second time. */
- /* layer: background, to show tranparency */
- glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255);
- glRectf(x1, y1, x1 + sizex, rect->ymax);
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_CHECKER_8PX);
- glRectf(x1, y1, x1 + sizex, rect->ymax);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ Gwn_VertFormat *format = immVertexFormat();
+ pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
+
+ /* Drawing the checkerboard. */
+ immUniform4f("color1", UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, 1.0f);
+ immUniform4f("color2", UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 1.0f);
+ immUniform1i("size", 8);
+ immRectf(pos_id, x1, y1, x1 + sizex, rect->ymax);
+ immUnbindProgram();
+
+ /* New format */
+ format = immVertexFormat();
+ pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ col_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
/* layer: color ramp */
- glEnable(GL_BLEND);
+ GPU_blend(true);
CBData *cbd = coba->data;
@@ -1122,7 +1446,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
v1[1] = y1 + sizey_solid;
v2[1] = rect->ymax;
- glBegin(GL_TRIANGLE_STRIP);
+ immBegin(GWN_PRIM_TRI_STRIP, (sizex + 1) * 2);
for (int a = 0; a <= sizex; a++) {
float pos = ((float)a) / sizex;
BKE_colorband_evaluate(coba, pos, colf);
@@ -1131,17 +1455,17 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
v1[0] = v2[0] = x1 + a;
- glColor4fv(colf);
- glVertex2fv(v1);
- glVertex2fv(v2);
+ immAttrib4fv(col_id, colf);
+ immVertex2fv(pos_id, v1);
+ immVertex2fv(pos_id, v2);
}
- glEnd();
+ immEnd();
/* layer: color ramp without alpha for reference when manipulating ramp properties */
v1[1] = y1;
v2[1] = y1 + sizey_solid;
- glBegin(GL_TRIANGLE_STRIP);
+ immBegin(GWN_PRIM_TRI_STRIP, (sizex + 1) * 2);
for (int a = 0; a <= sizex; a++) {
float pos = ((float)a) / sizex;
BKE_colorband_evaluate(coba, pos, colf);
@@ -1150,31 +1474,48 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
v1[0] = v2[0] = x1 + a;
- glColor4f(colf[0], colf[1], colf[2], 1.0f);
- glVertex2fv(v1);
- glVertex2fv(v2);
+ immAttrib4f(col_id, colf[0], colf[1], colf[2], 1.0f);
+ immVertex2fv(pos_id, v1);
+ immVertex2fv(pos_id, v2);
}
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
+
+ GPU_blend(false);
- glDisable(GL_BLEND);
+ /* New format */
+ format = immVertexFormat();
+ pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* layer: box outline */
- glColor4f(0.0, 0.0, 0.0, 1.0);
- fdrawbox(x1, y1, x1 + sizex, rect->ymax);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+ imm_draw_box_wire_2d(pos_id, x1, y1, x1 + sizex, rect->ymax);
/* layer: box outline */
- glEnable(GL_BLEND);
- glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
- fdrawline(x1, y1, x1 + sizex, y1);
- glColor4f(1.0f, 1.0f, 1.0f, 0.25f);
- fdrawline(x1, y1 - 1, x1 + sizex, y1 - 1);
- glDisable(GL_BLEND);
+ GPU_blend(true);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos_id, x1, y1);
+ immVertex2f(pos_id, x1 + sizex, y1);
+ immEnd();
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos_id, x1, y1 - 1);
+ immVertex2f(pos_id, x1 + sizex, y1 - 1);
+ immEnd();
+
+ GPU_blend(false);
/* layer: draw handles */
for (int a = 0; a < coba->tot; a++, cbd++) {
if (a != coba->cur) {
float pos = x1 + cbd->pos * (sizex - 1) + 1;
- ui_draw_colorband_handle(rect, pos, &cbd->r, display, false);
+ ui_draw_colorband_handle(pos_id, rect, pos, &cbd->r, display, false);
}
}
@@ -1182,117 +1523,102 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
if (coba->tot != 0) {
cbd = &coba->data[coba->cur];
float pos = x1 + cbd->pos * (sizex - 1) + 1;
- ui_draw_colorband_handle(rect, pos, &cbd->r, display, true);
+ ui_draw_colorband_handle(pos_id, rect, pos, &cbd->r, display, true);
}
+
+ immUnbindProgram();
}
void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
{
- static GLuint displist = 0;
+ /* sphere color */
float diffuse[3] = {1.0f, 1.0f, 1.0f};
+ float light[3];
float size;
/* backdrop */
- glColor3ubv((unsigned char *)wcol->inner);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f);
+ UI_draw_roundbox_3ubAlpha(true, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, (unsigned char *)wcol->inner, 255);
- /* sphere color */
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
/* setup lights */
- GPULightData light = {0};
- light.type = GPU_LIGHT_SUN;
- copy_v3_v3(light.diffuse, diffuse);
- zero_v3(light.specular);
- ui_but_v3_get(but, light.direction);
-
- GPU_basic_shader_light_set(0, &light);
- for (int a = 1; a < 8; a++)
- GPU_basic_shader_light_set(a, NULL);
-
- /* setup shader */
- GPU_basic_shader_colors(diffuse, NULL, 0, 1.0f);
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING);
+ ui_but_v3_get(but, light);
/* transform to button */
- glPushMatrix();
- glTranslatef(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect), 0.0f);
+ gpuPushMatrix();
if (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect))
- size = BLI_rcti_size_x(rect) / 200.f;
+ size = 0.5f * BLI_rcti_size_x(rect);
else
- size = BLI_rcti_size_y(rect) / 200.f;
-
- glScalef(size, size, MIN2(size, 1.0f));
-
- if (displist == 0) {
- GLUquadricObj *qobj;
+ size = 0.5f * BLI_rcti_size_y(rect);
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
+ gpuTranslate2f(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect));
+ gpuScaleUniform(size);
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_FILL);
- GPU_basic_shader_bind(GPU_basic_shader_bound_options());
- gluSphere(qobj, 100.0, 32, 24);
- gluDeleteQuadric(qobj);
-
- glEndList();
- }
-
- glCallList(displist);
+ Gwn_Batch *sphere = GPU_batch_preset_sphere(2);
+ GWN_batch_program_set_builtin(sphere, GPU_SHADER_SIMPLE_LIGHTING);
+ GWN_batch_uniform_4f(sphere, "color", diffuse[0], diffuse[1], diffuse[2], 1.0f);
+ GWN_batch_uniform_3fv(sphere, "light", light);
+ GWN_batch_draw(sphere);
/* restore */
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- GPU_default_lights();
glDisable(GL_CULL_FACE);
/* AA circle */
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
- glColor3ubv((unsigned char *)wcol->inner);
- glutil_draw_lined_arc(0.0f, M_PI * 2.0, 100.0f, 32);
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ubv((unsigned char *)wcol->inner);
+
+ GPU_blend(true);
+ GPU_line_smooth(true);
+ imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, 1.0f, 32);
+ GPU_blend(false);
+ GPU_line_smooth(false);
/* matrix after circle */
- glPopMatrix();
+ gpuPopMatrix();
- /* We disabled all blender lights above, so restore them here. */
- GPU_default_lights();
+ immUnbindProgram();
}
-static void ui_draw_but_curve_grid(const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step)
+static void ui_draw_but_curve_grid(unsigned int pos, const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step)
{
- glBegin(GL_LINES);
float dx = step * zoomx;
float fx = rect->xmin + zoomx * (-offsx);
if (fx > rect->xmin) fx -= dx * (floorf(fx - rect->xmin));
- while (fx < rect->xmax) {
- glVertex2f(fx, rect->ymin);
- glVertex2f(fx, rect->ymax);
- fx += dx;
- }
float dy = step * zoomy;
float fy = rect->ymin + zoomy * (-offsy);
if (fy > rect->ymin) fy -= dy * (floorf(fy - rect->ymin));
+
+ float line_count = (
+ floorf((rect->xmax - fx) / dx) + 1.0f +
+ floorf((rect->ymax - fy) / dy) + 1.0f);
+
+ immBegin(GWN_PRIM_LINES, (int)line_count * 2);
+ while (fx < rect->xmax) {
+ immVertex2f(pos, fx, rect->ymin);
+ immVertex2f(pos, fx, rect->ymax);
+ fx += dx;
+ }
while (fy < rect->ymax) {
- glVertex2f(rect->xmin, fy);
- glVertex2f(rect->xmax, fy);
+ immVertex2f(pos, rect->xmin, fy);
+ immVertex2f(pos, rect->xmax, fy);
fy += dy;
}
- glEnd();
+ immEnd();
}
static void gl_shaded_color(unsigned char *col, int shade)
{
- glColor3ub(col[0] - shade > 0 ? col[0] - shade : 0,
- col[1] - shade > 0 ? col[1] - shade : 0,
- col[2] - shade > 0 ? col[2] - shade : 0);
+ immUniformColor3ub(
+ col[0] - shade > 0 ? col[0] - shade : 0,
+ col[1] - shade > 0 ? col[1] - shade : 0,
+ col[2] - shade > 0 ? col[2] - shade : 0);
}
void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti *rect)
@@ -1309,19 +1635,21 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
CurveMap *cuma = &cumap->cm[cumap->cur];
/* need scissor test, curve can draw outside of boundary */
- GLint scissor[4];
- glGetIntegerv(GL_VIEWPORT, scissor);
+ int scissor[4];
+ GPU_scissor_get_i(scissor);
rcti scissor_new = {
- .xmin = ar->winrct.xmin + rect->xmin,
- .ymin = ar->winrct.ymin + rect->ymin,
- .xmax = ar->winrct.xmin + rect->xmax,
- .ymax = ar->winrct.ymin + rect->ymax
+ .xmin = rect->xmin,
+ .ymin = rect->ymin,
+ .xmax = rect->xmax,
+ .ymax = rect->ymax
};
- BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new);
- glScissor(scissor_new.xmin,
- scissor_new.ymin,
- BLI_rcti_size_x(&scissor_new),
- BLI_rcti_size_y(&scissor_new));
+ rcti scissor_region = {0, ar->winx, 0, ar->winy};
+ BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
+ GPU_scissor(
+ scissor_new.xmin,
+ scissor_new.ymin,
+ BLI_rcti_size_x(&scissor_new),
+ BLI_rcti_size_y(&scissor_new));
/* calculate offset and zoom */
float zoomx = (BLI_rcti_size_x(rect) - 2.0f) / BLI_rctf_size_x(&cumap->curr);
@@ -1329,9 +1657,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
float offsx = cumap->curr.xmin - (1.0f / zoomx);
float offsy = cumap->curr.ymin - (1.0f / zoomy);
- glLineWidth(1.0f);
-
- /* backdrop */
+ /* Do this first to not mess imm context */
if (but->a1 == UI_GRAD_H) {
/* magic trigger for curve backgrounds */
float col[3] = {0.0f, 0.0f, 0.0f}; /* dummy arg */
@@ -1344,96 +1670,106 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
};
ui_draw_gradient(&grid, col, UI_GRAD_H, 1.0f);
+ }
+ GPU_line_width(1.0f);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* backdrop */
+ if (but->a1 == UI_GRAD_H) {
/* grid, hsv uses different grid */
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4ub(0, 0, 0, 48);
- ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.1666666f);
- glDisable(GL_BLEND);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ immUniformColor4ub(0, 0, 0, 48);
+ ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.1666666f);
+ GPU_blend(false);
}
else {
if (cumap->flag & CUMA_DO_CLIP) {
gl_shaded_color((unsigned char *)wcol->inner, -20);
- glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- glColor3ubv((unsigned char *)wcol->inner);
- glRectf(rect->xmin + zoomx * (cumap->clipr.xmin - offsx),
- rect->ymin + zoomy * (cumap->clipr.ymin - offsy),
- rect->xmin + zoomx * (cumap->clipr.xmax - offsx),
- rect->ymin + zoomy * (cumap->clipr.ymax - offsy));
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ immUniformColor3ubv((unsigned char *)wcol->inner);
+ immRectf(pos,
+ rect->xmin + zoomx * (cumap->clipr.xmin - offsx),
+ rect->ymin + zoomy * (cumap->clipr.ymin - offsy),
+ rect->xmin + zoomx * (cumap->clipr.xmax - offsx),
+ rect->ymin + zoomy * (cumap->clipr.ymax - offsy));
}
else {
- glColor3ubv((unsigned char *)wcol->inner);
- glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ immUniformColor3ubv((unsigned char *)wcol->inner);
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
}
/* grid, every 0.25 step */
gl_shaded_color((unsigned char *)wcol->inner, -16);
- ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.25f);
+ ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.25f);
/* grid, every 1.0 step */
gl_shaded_color((unsigned char *)wcol->inner, -24);
- ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 1.0f);
+ ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 1.0f);
/* axes */
gl_shaded_color((unsigned char *)wcol->inner, -50);
- glBegin(GL_LINES);
- glVertex2f(rect->xmin, rect->ymin + zoomy * (-offsy));
- glVertex2f(rect->xmax, rect->ymin + zoomy * (-offsy));
- glVertex2f(rect->xmin + zoomx * (-offsx), rect->ymin);
- glVertex2f(rect->xmin + zoomx * (-offsx), rect->ymax);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 4);
+ immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (-offsy));
+ immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (-offsy));
+ immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymax);
+ immEnd();
}
/* cfra option */
/* XXX 2.48 */
#if 0
if (cumap->flag & CUMA_DRAW_CFRA) {
- glColor3ub(0x60, 0xc0, 0x40);
- glBegin(GL_LINES);
- glVertex2f(rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin);
- glVertex2f(rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax);
- glEnd();
+ immUniformColor3ub(0x60, 0xc0, 0x40);
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax);
+ immEnd();
}
#endif
/* sample option */
if (cumap->flag & CUMA_DRAW_SAMPLE) {
- glBegin(GL_LINES); /* will draw one of the following 3 lines */
+ immBegin(GWN_PRIM_LINES, 2); /* will draw one of the following 3 lines */
if (but->a1 == UI_GRAD_H) {
float tsample[3];
float hsv[3];
linearrgb_to_srgb_v3_v3(tsample, cumap->sample);
rgb_to_hsv_v(tsample, hsv);
- glColor3ub(240, 240, 240);
+ immUniformColor3ub(240, 240, 240);
- glVertex2f(rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin);
- glVertex2f(rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax);
+ immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax);
}
else if (cumap->cur == 3) {
float lum = IMB_colormanagement_get_luminance(cumap->sample);
- glColor3ub(240, 240, 240);
+ immUniformColor3ub(240, 240, 240);
- glVertex2f(rect->xmin + zoomx * (lum - offsx), rect->ymin);
- glVertex2f(rect->xmin + zoomx * (lum - offsx), rect->ymax);
+ immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymax);
}
else {
if (cumap->cur == 0)
- glColor3ub(240, 100, 100);
+ immUniformColor3ub(240, 100, 100);
else if (cumap->cur == 1)
- glColor3ub(100, 240, 100);
+ immUniformColor3ub(100, 240, 100);
else
- glColor3ub(100, 100, 240);
+ immUniformColor3ub(100, 100, 240);
- glVertex2f(rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin);
- glVertex2f(rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax);
+ immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax);
}
- glEnd();
+ immEnd();
}
/* the curve */
- glColor3ubv((unsigned char *)wcol->item);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glBegin(GL_LINE_STRIP);
+ immUniformColor3ubv((unsigned char *)wcol->item);
+ GPU_line_smooth(true);
+ GPU_blend(true);
+ immBegin(GWN_PRIM_LINE_STRIP, (CM_TABLE + 1) + 2);
if (cuma->table == NULL)
curvemapping_changed(cumap, false);
@@ -1442,55 +1778,70 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
/* first point */
if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
- glVertex2f(rect->xmin, rect->ymin + zoomy * (cmp[0].y - offsy));
+ immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (cmp[0].y - offsy));
}
else {
float fx = rect->xmin + zoomx * (cmp[0].x - offsx + cuma->ext_in[0]);
float fy = rect->ymin + zoomy * (cmp[0].y - offsy + cuma->ext_in[1]);
- glVertex2f(fx, fy);
+ immVertex2f(pos, fx, fy);
}
for (int a = 0; a <= CM_TABLE; a++) {
float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
- glVertex2f(fx, fy);
+ immVertex2f(pos, fx, fy);
}
/* last point */
if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
- glVertex2f(rect->xmax, rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy));
+ immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy));
}
else {
float fx = rect->xmin + zoomx * (cmp[CM_TABLE].x - offsx - cuma->ext_out[0]);
float fy = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy - cuma->ext_out[1]);
- glVertex2f(fx, fy);
+ immVertex2f(pos, fx, fy);
}
- glEnd();
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ immEnd();
+ GPU_line_smooth(false);
+ GPU_blend(false);
+ immUnbindProgram();
/* the points, use aspect to make them visible on edges */
+ format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
cmp = cuma->curve;
- glPointSize(3.0f);
- glBegin(GL_POINTS);
+ GPU_point_size(3.0f);
+ immBegin(GWN_PRIM_POINTS, cuma->totpoint);
for (int a = 0; a < cuma->totpoint; a++) {
+ float color[4];
if (cmp[a].flag & CUMA_SELECT)
- UI_ThemeColor(TH_TEXT_HI);
+ UI_GetThemeColor4fv(TH_TEXT_HI, color);
else
- UI_ThemeColor(TH_TEXT);
+ UI_GetThemeColor4fv(TH_TEXT, color);
float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
- glVertex2f(fx, fy);
+ immAttrib4fv(col, color);
+ immVertex2f(pos, fx, fy);
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
/* restore scissortest */
- glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
/* outline */
- glColor3ubv((unsigned char *)wcol->outline);
- fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3ubv((unsigned char *)wcol->outline);
+ imm_draw_box_wire_2d(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+
+ immUnbindProgram();
}
-void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
+void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
{
bool ok = false;
MovieClipScopes *scopes = (MovieClipScopes *)but->poin;
@@ -1505,21 +1856,22 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
int width = BLI_rctf_size_x(&rect) + 1;
int height = BLI_rctf_size_y(&rect);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
/* need scissor test, preview image can draw outside of boundary */
- GLint scissor[4];
- glGetIntegerv(GL_VIEWPORT, scissor);
- glScissor(ar->winrct.xmin + (rect.xmin - 1),
- ar->winrct.ymin + (rect.ymin - 1),
- (rect.xmax + 1) - (rect.xmin - 1),
- (rect.ymax + 1) - (rect.ymin - 1));
+ int scissor[4];
+ GPU_scissor_get_i(scissor);
+ GPU_scissor(
+ (rect.xmin - 1),
+ (rect.ymin - 1),
+ (rect.xmax + 1) - (rect.xmin - 1),
+ (rect.ymax + 1) - (rect.ymin - 1));
if (scopes->track_disabled) {
- glColor4f(0.7f, 0.3f, 0.3f, 0.3f);
+ float color[4] = {0.7f, 0.3f, 0.3f, 0.3f};
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
ok = true;
}
@@ -1547,69 +1899,79 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
}
if (!ok && scopes->track_preview) {
- glPushMatrix();
+ gpuPushMatrix();
/* draw content of pattern area */
- glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, scissor[2], scissor[3]);
+ GPU_scissor(rect.xmin, rect.ymin, scissor[2], scissor[3]);
if (width > 0 && height > 0) {
ImBuf *drawibuf = scopes->track_preview;
+ float col_sel[4], col_outline[4];
if (scopes->use_track_mask) {
- glColor4f(0.0f, 0.0f, 0.0f, 0.3f);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
}
- glaDrawPixelsSafe(
- rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y,
- drawibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, drawibuf->rect);
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state, rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, drawibuf->rect, 1.0f, 1.0f, NULL);
/* draw cross for pixel position */
- glTranslatef(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1], 0.f);
- glScissor(ar->winrct.xmin + rect.xmin,
- ar->winrct.ymin + rect.ymin,
- BLI_rctf_size_x(&rect),
- BLI_rctf_size_y(&rect));
-
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE);
-
- for (int a = 0; a < 2; a++) {
- if (a == 1) {
- GPU_basic_shader_bind_enable(GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(3, 0xAAAA);
- UI_ThemeColor(TH_SEL_MARKER);
- }
- else {
- UI_ThemeColor(TH_MARKER_OUTLINE);
+ gpuTranslate2f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1]);
+ GPU_scissor(
+ rect.xmin,
+ rect.ymin,
+ BLI_rctf_size_x(&rect),
+ BLI_rctf_size_y(&rect));
+
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+ UI_GetThemeColor4fv(TH_SEL_MARKER, col_sel);
+ UI_GetThemeColor4fv(TH_MARKER_OUTLINE, col_outline);
+
+ /* Do stipple cross with geometry */
+ immBegin(GWN_PRIM_LINES, 7 * 2 * 2);
+ float pos_sel[8] = {-10.0f, -7.0f, -4.0f, -1.0f, 2.0f, 5.0f, 8.0f, 11.0f};
+ for (int axe = 0; axe < 2; ++axe) {
+ for (int i = 0; i < 7; ++i) {
+ float x1 = pos_sel[i] * (1 - axe);
+ float y1 = pos_sel[i] * axe;
+ float x2 = pos_sel[i + 1] * (1 - axe);
+ float y2 = pos_sel[i + 1] * axe;
+
+ if (i % 2 == 1)
+ immAttrib4fv(col, col_sel);
+ else
+ immAttrib4fv(col, col_outline);
+
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
}
-
- glBegin(GL_LINES);
- glVertex2f(-10.0f, 0.0f);
- glVertex2f(10.0f, 0.0f);
- glVertex2f(0.0f, -10.0f);
- glVertex2f(0.0f, 10.0f);
- glEnd();
}
+ immEnd();
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ immUnbindProgram();
}
- glPopMatrix();
+ gpuPopMatrix();
ok = true;
}
if (!ok) {
- glColor4f(0.f, 0.f, 0.f, 0.3f);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
}
/* outline */
draw_scope_end(&rect, scissor);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
@@ -1631,93 +1993,145 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol
0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
};
- GLint scissor[4];
+ int scissor[4];
/* need scissor test, can draw outside of boundary */
- glGetIntegerv(GL_VIEWPORT, scissor);
+ GPU_scissor_get_i(scissor);
rcti scissor_new = {
- .xmin = ar->winrct.xmin + recti->xmin,
- .ymin = ar->winrct.ymin + recti->ymin,
- .xmax = ar->winrct.xmin + recti->xmax,
- .ymax = ar->winrct.ymin + recti->ymax
+ .xmin = recti->xmin,
+ .ymin = recti->ymin,
+ .xmax = recti->xmax,
+ .ymax = recti->ymax
};
- BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new);
- glScissor(scissor_new.xmin,
- scissor_new.ymin,
- BLI_rcti_size_x(&scissor_new),
- BLI_rcti_size_y(&scissor_new));
+ rcti scissor_region = {0, ar->winx, 0, ar->winy};
- glColor4ubv(but->col);
+ BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
+ GPU_scissor(
+ scissor_new.xmin,
+ scissor_new.ymin,
+ BLI_rcti_size_x(&scissor_new),
+ BLI_rcti_size_y(&scissor_new));
float x = 0.5f * (recti->xmin + recti->xmax);
float y = 0.5f * (recti->ymin + recti->ymax);
- glEnable(GL_BLEND);
- glBegin(GL_POLYGON);
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv(but->col);
+
+ GPU_blend(true);
+ immBegin(GWN_PRIM_TRI_FAN, 16);
for (int a = 0; a < 16; a++)
- glVertex2f(x + size * si[a], y + size * co[a]);
- glEnd();
+ immVertex2f(pos, x + size * si[a], y + size * co[a]);
+ immEnd();
- glColor4ub(0, 0, 0, 150);
- glLineWidth(1);
- glEnable(GL_LINE_SMOOTH);
- glBegin(GL_LINE_LOOP);
+ immUniformColor4ub(0, 0, 0, 150);
+ GPU_line_width(1);
+ GPU_line_smooth(true);
+ immBegin(GWN_PRIM_LINE_LOOP, 16);
for (int a = 0; a < 16; a++)
- glVertex2f(x + size * si[a], y + size * co[a]);
- glEnd();
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ immVertex2f(pos, x + size * si[a], y + size * co[a]);
+ immEnd();
+ GPU_line_smooth(false);
+ GPU_blend(false);
+
+ immUnbindProgram();
/* restore scissortest */
- glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
}
/* ****************************************************** */
+/* TODO: high quality UI drop shadows using GLSL shader and single draw call
+ * would replace / modify the following 3 functions - merwin
+ */
-static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha)
+static void ui_shadowbox(unsigned pos, unsigned color, float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha)
{
+ /* v1-_
+ * | -_v2
+ * | |
+ * | |
+ * | |
+ * v7_______v3____v4
+ * \ | /
+ * \ | _v5
+ * v8______v6_-
+ */
+ const float v1[2] = {maxx, maxy - 0.3f * shadsize};
+ const float v2[2] = {maxx + shadsize, maxy - 0.75f * shadsize};
+ const float v3[2] = {maxx, miny};
+ const float v4[2] = {maxx + shadsize, miny};
+
+ const float v5[2] = {maxx + 0.7f * shadsize, miny - 0.7f * shadsize};
+
+ const float v6[2] = {maxx, miny - shadsize};
+ const float v7[2] = {minx + 0.3f * shadsize, miny};
+ const float v8[2] = {minx + 0.5f * shadsize, miny - shadsize};
+
/* right quad */
- glColor4ub(0, 0, 0, alpha);
- glVertex2f(maxx, miny);
- glVertex2f(maxx, maxy - 0.3f * shadsize);
- glColor4ub(0, 0, 0, 0);
- glVertex2f(maxx + shadsize, maxy - 0.75f * shadsize);
- glVertex2f(maxx + shadsize, miny);
+ immAttrib4ub(color, 0, 0, 0, alpha);
+ immVertex2fv(pos, v3);
+ immVertex2fv(pos, v1);
+ immAttrib4ub(color, 0, 0, 0, 0);
+ immVertex2fv(pos, v2);
+
+ immVertex2fv(pos, v2);
+ immVertex2fv(pos, v4);
+ immAttrib4ub(color, 0, 0, 0, alpha);
+ immVertex2fv(pos, v3);
/* corner shape */
- glColor4ub(0, 0, 0, alpha);
- glVertex2f(maxx, miny);
- glColor4ub(0, 0, 0, 0);
- glVertex2f(maxx + shadsize, miny);
- glVertex2f(maxx + 0.7f * shadsize, miny - 0.7f * shadsize);
- glVertex2f(maxx, miny - shadsize);
+ /* immAttrib4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */
+ immVertex2fv(pos, v3);
+ immAttrib4ub(color, 0, 0, 0, 0);
+ immVertex2fv(pos, v4);
+ immVertex2fv(pos, v5);
+
+ immVertex2fv(pos, v5);
+ immVertex2fv(pos, v6);
+ immAttrib4ub(color, 0, 0, 0, alpha);
+ immVertex2fv(pos, v3);
/* bottom quad */
- glColor4ub(0, 0, 0, alpha);
- glVertex2f(minx + 0.3f * shadsize, miny);
- glVertex2f(maxx, miny);
- glColor4ub(0, 0, 0, 0);
- glVertex2f(maxx, miny - shadsize);
- glVertex2f(minx + 0.5f * shadsize, miny - shadsize);
+ /* immAttrib4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */
+ immVertex2fv(pos, v3);
+ immAttrib4ub(color, 0, 0, 0, 0);
+ immVertex2fv(pos, v6);
+ immVertex2fv(pos, v8);
+
+ immVertex2fv(pos, v8);
+ immAttrib4ub(color, 0, 0, 0, alpha);
+ immVertex2fv(pos, v7);
+ immVertex2fv(pos, v3);
}
void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy)
{
- glEnable(GL_BLEND);
+ GPU_blend(true);
- glBegin(GL_QUADS);
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ immBegin(GWN_PRIM_TRIS, 54);
/* accumulated outline boxes to make shade not linear, is more pleasant */
- ui_shadowbox(minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8);
- ui_shadowbox(minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8);
- ui_shadowbox(minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8);
+ ui_shadowbox(pos, color, minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8);
+ ui_shadowbox(pos, color, minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8);
+ ui_shadowbox(pos, color, minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8);
- glEnd();
+ immEnd();
- glDisable(GL_BLEND);
+ immUnbindProgram();
+
+ GPU_blend(false);
}
@@ -1725,8 +2139,8 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha
{
float rad;
- if (radius > (BLI_rctf_size_y(rct) - 10.0f) / 2.0f)
- rad = (BLI_rctf_size_y(rct) - 10.0f) / 2.0f;
+ if (radius > (BLI_rctf_size_y(rct) - 10.0f) * 0.5f)
+ rad = (BLI_rctf_size_y(rct) - 10.0f) * 0.5f;
else
rad = radius;
@@ -1741,35 +2155,47 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha
a = i * aspect;
}
- glEnable(GL_BLEND);
-
+ GPU_blend(true);
const float dalpha = alpha * 2.0f / 255.0f;
float calpha = dalpha;
- for (; i--; a -= aspect) {
+ float visibility = 1.0f;
+ for (; i--;) {
/* alpha ranges from 2 to 20 or so */
- glColor4f(0.0f, 0.0f, 0.0f, calpha);
+#if 0 /* Old Method (pre 2.8) */
+ float color[4] = {0.0f, 0.0f, 0.0f, calpha};
+ UI_draw_roundbox_4fv(true, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color);
+#endif
+ /* Compute final visibility to match old method result. */
+ /* TODO we could just find a better fit function inside the shader instead of this. */
+ visibility = visibility * (1.0f - calpha);
calpha += dalpha;
-
- UI_draw_roundbox_gl_mode(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a);
}
- /* outline emphasis */
- glEnable(GL_LINE_SMOOTH);
- glColor4ub(0, 0, 0, 100);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f);
- glDisable(GL_LINE_SMOOTH);
+ uiWidgetBaseParameters widget_params = {
+ .recti.xmin = rct->xmin, .recti.ymin = rct->ymin,
+ .recti.xmax = rct->xmax, .recti.ymax = rct->ymax - 10.0f,
+ .rect.xmin = rct->xmin - a, .rect.ymin = rct->ymin - a,
+ .rect.xmax = rct->xmax + a, .rect.ymax = rct->ymax - 10.0f + a,
+ .radi = rad,
+ .rad = rad + a,
+ .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
+ .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
+ .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
+ .alpha_discard = 1.0f,
+ };
- glDisable(GL_BLEND);
-}
+ Gwn_Batch *batch = ui_batch_roundbox_shadow_get();
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_SHADOW);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 4, (float *)&widget_params);
+ GWN_batch_uniform_1f(batch, "alpha", 1.0f - visibility);
+ GWN_batch_draw(batch);
-/**
- * Reset GL state (keep minimal).
- *
- * \note Blender's internal code doesn't assume these are reset,
- * but external callbacks may depend on their state.
- */
-void UI_reinit_gl_state(void)
-{
- glLineWidth(1.0f);
- glPointSize(1.0f);
+ /* outline emphasis */
+ GPU_line_smooth(true);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.4f};
+ UI_draw_roundbox_4fv(false, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f, color);
+ GPU_line_smooth(false);
+
+ GPU_blend(false);
}
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index fafe5f48f75..eb8fff471e2 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -135,8 +135,8 @@ void eyedropper_draw_cursor_text(const struct bContext *C, const ARegion *ar, co
wmWindow *win = CTX_wm_window(C);
int x = win->eventstate->x;
int y = win->eventstate->y;
- const unsigned char fg[4] = {255, 255, 255, 255};
- const unsigned char bg[4] = {0, 0, 0, 50};
+ const float col_fg[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ const float col_bg[4] = {0.0f, 0.0f, 0.0f, 0.2f};
if ((name[0] == '\0') ||
@@ -150,7 +150,7 @@ void eyedropper_draw_cursor_text(const struct bContext *C, const ARegion *ar, co
y += U.widget_unit;
- UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, fg, bg);
+ UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg);
}
@@ -165,8 +165,8 @@ void eyedropper_draw_cursor_text(const struct bContext *C, const ARegion *ar, co
*/
uiBut *eyedropper_get_property_button_under_mouse(bContext *C, const wmEvent *event)
{
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, event->x, event->y);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->x, event->y);
ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_ANY, event->x, event->y);
uiBut *but = ui_but_find_mouse_over(ar, event);
diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c
index 7dd7de0817e..73efc59feb7 100644
--- a/source/blender/editors/interface/interface_eyedropper_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_color.c
@@ -133,8 +133,8 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
{
/* we could use some clever */
Main *bmain = CTX_data_main(C);
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
const char *display_device = CTX_data_scene(C)->display_settings.display_device;
struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
diff --git a/source/blender/editors/interface/interface_eyedropper_datablock.c b/source/blender/editors/interface/interface_eyedropper_datablock.c
index 2bb575558fc..b1e649f4abe 100644
--- a/source/blender/editors/interface/interface_eyedropper_datablock.c
+++ b/source/blender/editors/interface/interface_eyedropper_datablock.c
@@ -150,8 +150,8 @@ static void datadropper_exit(bContext *C, wmOperator *op)
static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int my, ID **r_id)
{
/* we could use some clever */
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = BKE_screen_find_area_xy(win->screen, -1, mx, my);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = BKE_screen_find_area_xy(screen, -1, mx, my);
ScrArea *area_prev = CTX_wm_area(C);
ARegion *ar_prev = CTX_wm_region(C);
diff --git a/source/blender/editors/interface/interface_eyedropper_depth.c b/source/blender/editors/interface/interface_eyedropper_depth.c
index 954259140c3..fb125a3845b 100644
--- a/source/blender/editors/interface/interface_eyedropper_depth.c
+++ b/source/blender/editors/interface/interface_eyedropper_depth.c
@@ -45,6 +45,8 @@
#include "BKE_screen.h"
#include "BKE_unit.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "UI_interface.h"
@@ -152,10 +154,10 @@ static void depthdropper_exit(bContext *C, wmOperator *op)
static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth)
{
/* we could use some clever */
- Main *bmain = CTX_data_main(C);
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my);
- Scene *scene = win->screen->scene;
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
+ Scene *scene = CTX_data_scene(C);
+
UnitSettings *unit = &scene->unit;
const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
@@ -168,6 +170,7 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx,
if (sa->spacetype == SPACE_VIEW3D) {
ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
if (ar) {
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
/* weak, we could pass in some reference point */
@@ -185,7 +188,7 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx,
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(bmain, scene, ar, v3d, mval, co, true, NULL)) {
+ if (ED_view3d_autodist(depsgraph, ar, v3d, mval, co, true, NULL)) {
const float mval_center_fl[2] = {
(float)ar->winx / 2,
(float)ar->winy / 2};
diff --git a/source/blender/editors/interface/interface_eyedropper_driver.c b/source/blender/editors/interface/interface_eyedropper_driver.c
index d6569bd840c..852f7ea71b6 100644
--- a/source/blender/editors/interface/interface_eyedropper_driver.c
+++ b/source/blender/editors/interface/interface_eyedropper_driver.c
@@ -42,7 +42,9 @@
#include "BKE_context.h"
#include "BKE_animsys.h"
-#include "BKE_depsgraph.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -130,8 +132,8 @@ static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *eve
if (success) {
/* send updates */
UI_context_update_anim_flag(C);
- DAG_relations_tag_update(CTX_data_main(C));
- DAG_id_tag_update(ddr->ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_relations_tag_update(CTX_data_main(C));
+ DEG_id_tag_update(ddr->ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
}
}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 06b6099cec7..ac7ed3d5106 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -38,11 +38,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_brush_types.h"
-#include "DNA_sensor_types.h"
-#include "DNA_controller_types.h"
-#include "DNA_actuator_types.h"
-#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -72,6 +68,7 @@
#include "ED_undo.h"
#include "UI_interface.h"
+#include "UI_view2d.h"
#include "BLF_api.h"
@@ -109,8 +106,6 @@
#define UI_MAX_PASSWORD_STR 128
/* proto */
-static void ui_but_smart_controller_add(bContext *C, uiBut *from, uiBut *to);
-static void ui_but_link_add(bContext *C, uiBut *from, uiBut *to);
static int ui_do_but_EXIT(bContext *C, uiBut *but, struct uiHandleButtonData *data, const wmEvent *event);
static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but_b);
static void ui_textedit_string_set(uiBut *but, struct uiHandleButtonData *data, const char *str);
@@ -125,7 +120,7 @@ static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEve
#define BUTTON_FLASH_DELAY 0.020
#define MENU_SCROLL_INTERVAL 0.1
#define PIE_MENU_INTERVAL 0.01
-#define BUTTON_AUTO_OPEN_THRESH 0.3
+#define BUTTON_AUTO_OPEN_THRESH 0.2
#define BUTTON_MOUSE_TOWARDS_THRESH 1.0
/* pixels to move the cursor to get out of keyboard navigation */
#define BUTTON_KEYNAV_PX_LIMIT 8
@@ -276,6 +271,7 @@ typedef struct uiHandleButtonData {
/* booleans (could be made into flags) */
bool cancel, escapecancel;
bool applied, applied_interactive;
+ bool changed_cursor;
wmTimer *flashtimer;
/* edited value */
@@ -619,11 +615,8 @@ PointerRNA *ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext,
static void popup_check(bContext *C, wmOperator *op)
{
- if (op && op->type->check && op->type->check(C, op)) {
- /* check for popup and re-layout buttons */
- ARegion *ar_menu = CTX_wm_menu(C);
- if (ar_menu)
- ED_region_tag_refresh_ui(ar_menu);
+ if (op && op->type->check) {
+ op->type->check(C, op);
}
}
@@ -704,8 +697,7 @@ static void ui_apply_but_undo(uiBut *but)
const char *str = NULL;
/* define which string to use for undo */
- if (ELEM(but->type, UI_BTYPE_LINK, UI_BTYPE_INLINK)) str = "Add button link";
- else if (but->type == UI_BTYPE_MENU) str = but->drawstr;
+ if (but->type == UI_BTYPE_MENU) str = but->drawstr;
else if (but->drawstr[0]) str = but->drawstr;
else str = but->tip;
@@ -917,6 +909,20 @@ static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
data->applied = true;
}
+static void ui_apply_but_TAB(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ if (data->str) {
+ ui_but_string_set(C, but, data->str);
+ ui_but_update_edited(but);
+ }
+ else {
+ ui_apply_but_func(C, but);
+ }
+
+ data->retval = but->retval;
+ data->applied = true;
+}
+
static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data)
{
if (data->str) {
@@ -1219,6 +1225,9 @@ static bool ui_drag_toggle_but_is_supported(const uiBut *but)
if (ui_but_is_bool(but)) {
return true;
}
+ else if (UI_but_is_decorator(but)) {
+ return ELEM(but->icon, ICON_SPACE2, ICON_SPACE3, ICON_DOT, ICON_LIBRARY_DATA_OVERRIDE);
+ }
else {
return false;
}
@@ -1229,6 +1238,9 @@ static bool ui_drag_toggle_but_is_pushed(uiBut *but)
if (ui_but_is_bool(but)) {
return ui_but_is_pushed(but);
}
+ else if (UI_but_is_decorator(but)) {
+ return (but->icon == ICON_SPACE2);
+ }
else {
return false;
}
@@ -1239,7 +1251,6 @@ typedef struct uiDragToggleHandle {
bool is_init;
bool is_set;
float but_cent_start[2];
- eButType but_type_start;
bool xy_lock[2];
int xy_init[2];
@@ -1247,7 +1258,7 @@ typedef struct uiDragToggleHandle {
} uiDragToggleHandle;
static bool ui_drag_toggle_set_xy_xy(
- bContext *C, ARegion *ar, const bool is_set, const eButType but_type_start,
+ bContext *C, ARegion *ar, const bool is_set,
const int xy_src[2], const int xy_dst[2])
{
/* popups such as layers won't re-evaluate on redraw */
@@ -1271,7 +1282,7 @@ static bool ui_drag_toggle_set_xy_xy(
if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) {
/* execute the button */
- if (ui_drag_toggle_but_is_supported(but) && but->type == but_type_start) {
+ if (ui_drag_toggle_but_is_supported(but)) {
/* is it pressed? */
bool is_set_but = ui_drag_toggle_but_is_pushed(but);
if (is_set_but != is_set) {
@@ -1345,7 +1356,7 @@ static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const
/* touch all buttons between last mouse coord and this one */
- do_draw = ui_drag_toggle_set_xy_xy(C, ar, drag_info->is_set, drag_info->but_type_start, drag_info->xy_last, xy);
+ do_draw = ui_drag_toggle_set_xy_xy(C, ar, drag_info->is_set, drag_info->xy_last, xy);
if (do_draw) {
ED_region_tag_redraw(ar);
@@ -1725,7 +1736,6 @@ static bool ui_but_drag_init(
drag_info->is_set = ui_drag_toggle_but_is_pushed(but);
drag_info->but_cent_start[0] = BLI_rctf_cent_x(&but->rect);
drag_info->but_cent_start[1] = BLI_rctf_cent_y(&but->rect);
- drag_info->but_type_start = but->type;
copy_v2_v2_int(drag_info->xy_init, &event->x);
copy_v2_v2_int(drag_info->xy_last, &event->x);
@@ -1792,223 +1802,6 @@ static bool ui_but_drag_init(
/* ********************** linklines *********************** */
-static void ui_linkline_remove_active(uiBlock *block)
-{
- uiBut *but;
- uiLink *link;
- uiLinkLine *line, *nline;
- int a, b;
-
- for (but = block->buttons.first; but; but = but->next) {
- if (but->type == UI_BTYPE_LINK && but->link) {
- for (line = but->link->lines.first; line; line = nline) {
- nline = line->next;
-
- if (line->flag & UI_SELECT) {
- BLI_remlink(&but->link->lines, line);
-
- link = line->from->link;
-
- /* are there more pointers allowed? */
- if (link->ppoin) {
-
- if (*(link->totlink) == 1) {
- *(link->totlink) = 0;
- MEM_freeN(*(link->ppoin));
- *(link->ppoin) = NULL;
- }
- else {
- b = 0;
- for (a = 0; a < (*(link->totlink)); a++) {
-
- if ((*(link->ppoin))[a] != line->to->poin) {
- (*(link->ppoin))[b] = (*(link->ppoin))[a];
- b++;
- }
- }
- (*(link->totlink))--;
- }
- }
- else {
- *(link->poin) = NULL;
- }
-
- MEM_freeN(line);
- }
- }
- }
- }
-}
-
-
-static uiLinkLine *ui_but_find_link(uiBut *from, uiBut *to)
-{
- uiLinkLine *line;
- uiLink *link;
-
- link = from->link;
- if (link) {
- for (line = link->lines.first; line; line = line->next) {
- if (line->from == from && line->to == to) {
- return line;
- }
- }
- }
- return NULL;
-}
-
-/* XXX BAD BAD HACK, fixme later **************** */
-/* Try to add an AND Controller between the sensor and the actuator logic bricks and to connect them all */
-static void ui_but_smart_controller_add(bContext *C, uiBut *from, uiBut *to)
-{
- Object *ob = NULL;
- bSensor *sens_iter;
- bActuator *act_to, *act_iter;
- bController *cont;
- bController ***sens_from_links;
- uiBut *tmp_but;
-
- uiLink *link = from->link;
-
- PointerRNA props_ptr, object_ptr;
-
- if (link->ppoin)
- sens_from_links = (bController ***)(link->ppoin);
- else return;
-
- act_to = (bActuator *)(to->poin);
-
- /* (1) get the object */
- CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects)
- {
- for (sens_iter = ob_iter->sensors.first; sens_iter; sens_iter = sens_iter->next) {
- if (&(sens_iter->links) == sens_from_links) {
- ob = ob_iter;
- break;
- }
- }
- if (ob) break;
- } CTX_DATA_END;
-
- if (!ob) return;
-
- /* (2) check if the sensor and the actuator are from the same object */
- for (act_iter = ob->actuators.first; act_iter; act_iter = (bActuator *)act_iter->next) {
- if (act_iter == act_to)
- break;
- }
-
- /* only works if the sensor and the actuator are from the same object */
- if (!act_iter) return;
-
- /* in case the linked controller is not the active one */
- RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
-
- WM_operator_properties_create(&props_ptr, "LOGIC_OT_controller_add");
- RNA_string_set(&props_ptr, "object", ob->id.name + 2);
-
- /* (3) add a new controller */
- if (WM_operator_name_call(C, "LOGIC_OT_controller_add", WM_OP_EXEC_DEFAULT, &props_ptr) & OPERATOR_FINISHED) {
- cont = (bController *)ob->controllers.last;
- /* Quick fix to make sure we always have an AND controller.
- * It might be nicer to make sure the operator gives us the right one though... */
- cont->type = CONT_LOGIC_AND;
-
- /* (4) link the sensor->controller->actuator */
- tmp_but = MEM_callocN(sizeof(uiBut), "uiBut");
- UI_but_link_set(
- tmp_but, (void **)&cont, (void ***)&(cont->links),
- &cont->totlinks, from->link->tocode, (int)to->hardmin);
- tmp_but->hardmin = from->link->tocode;
- tmp_but->poin = (char *)cont;
-
- tmp_but->type = UI_BTYPE_INLINK;
- ui_but_link_add(C, from, tmp_but);
-
- tmp_but->type = UI_BTYPE_LINK;
- ui_but_link_add(C, tmp_but, to);
-
- /* (5) garbage collection */
- MEM_freeN(tmp_but->link);
- MEM_freeN(tmp_but);
- }
- WM_operator_properties_free(&props_ptr);
-}
-
-static void ui_but_link_add(bContext *C, uiBut *from, uiBut *to)
-{
- /* in 'from' we have to add a link to 'to' */
- uiLink *link;
- uiLinkLine *line;
- void **oldppoin;
- int a;
-
- if ((line = ui_but_find_link(from, to))) {
- line->flag |= UI_SELECT;
- ui_linkline_remove_active(from->block);
- return;
- }
-
- if (from->type == UI_BTYPE_INLINK && to->type == UI_BTYPE_INLINK) {
- return;
- }
- else if (from->type == UI_BTYPE_LINK && to->type == UI_BTYPE_INLINK) {
- if (from->link->tocode != (int)to->hardmin) {
- ui_but_smart_controller_add(C, from, to);
- return;
- }
- }
- else if (from->type == UI_BTYPE_INLINK && to->type == UI_BTYPE_LINK) {
- if (to->link->tocode == (int)from->hardmin) {
- return;
- }
- }
-
- link = from->link;
-
- /* are there more pointers allowed? */
- if (link->ppoin) {
- oldppoin = *(link->ppoin);
-
- (*(link->totlink))++;
- *(link->ppoin) = MEM_callocN(*(link->totlink) * sizeof(void *), "new link");
-
- for (a = 0; a < (*(link->totlink)) - 1; a++) {
- (*(link->ppoin))[a] = oldppoin[a];
- }
- (*(link->ppoin))[a] = to->poin;
-
- if (oldppoin) MEM_freeN(oldppoin);
- }
- else {
- *(link->poin) = to->poin;
- }
-
-}
-
-
-static void ui_apply_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data)
-{
- ARegion *ar = CTX_wm_region(C);
- uiBut *bt;
-
- for (bt = but->block->buttons.first; bt; bt = bt->next) {
- if (ui_but_contains_point_px(ar, bt, but->linkto[0] + ar->winrct.xmin, but->linkto[1] + ar->winrct.ymin) )
- break;
- }
- if (bt && bt != but) {
- if (!ELEM(bt->type, UI_BTYPE_LINK, UI_BTYPE_INLINK) || !ELEM(but->type, UI_BTYPE_LINK, UI_BTYPE_INLINK))
- return;
-
- if (but->type == UI_BTYPE_LINK) ui_but_link_add(C, but, bt);
- else ui_but_link_add(C, bt, but);
-
- ui_apply_but_func(C, but);
- data->retval = but->retval;
- }
- data->applied = true;
-}
-
static void ui_apply_but_IMAGE(bContext *C, uiBut *but, uiHandleButtonData *data)
{
ui_apply_but_func(C, but);
@@ -2127,6 +1920,9 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
case UI_BTYPE_LISTROW:
ui_apply_but_ROW(C, block, but, data);
break;
+ case UI_BTYPE_TAB:
+ ui_apply_but_TAB(C, but, data);
+ break;
case UI_BTYPE_SCROLL:
case UI_BTYPE_GRIP:
case UI_BTYPE_NUM:
@@ -2162,10 +1958,6 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
case UI_BTYPE_HOTKEY_EVENT:
ui_apply_but_BUT(C, but, data);
break;
- case UI_BTYPE_LINK:
- case UI_BTYPE_INLINK:
- ui_apply_but_LINK(C, but, data);
- break;
case UI_BTYPE_IMAGE:
ui_apply_but_IMAGE(C, but, data);
break;
@@ -3179,6 +2971,9 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
ui_searchbox_free(C, data->searchbox);
data->searchbox = NULL;
+ if (but->free_search_arg) {
+ MEM_SAFE_FREE(but->search_arg);
+ }
}
but->editstr = NULL;
@@ -3658,6 +3453,7 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat
uiBlockCreateFunc func = NULL;
uiBlockHandleCreateFunc handlefunc = NULL;
uiMenuCreateFunc menufunc = NULL;
+ uiMenuCreateFunc popoverfunc = NULL;
void *arg = NULL;
switch (but->type) {
@@ -3677,6 +3473,11 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat
menufunc = but->menu_create_func;
arg = but->poin;
break;
+ case UI_BTYPE_POPOVER:
+ BLI_assert(but->menu_create_func);
+ popoverfunc = but->menu_create_func;
+ arg = but->poin;
+ break;
case UI_BTYPE_COLOR:
ui_but_v3_get(but, data->origvec);
copy_v3_v3(data->vec, data->origvec);
@@ -3701,6 +3502,11 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat
if (but->block->handle)
data->menu->popup = but->block->handle->popup;
}
+ else if (popoverfunc) {
+ data->menu = ui_popover_panel_create(C, data->region, but, popoverfunc, arg);
+ if (but->block->handle)
+ data->menu->popup = but->block->handle->popup;
+ }
#ifdef USE_ALLSELECT
{
@@ -3947,6 +3753,43 @@ static bool ui_but_is_mouse_over_icon_extra(const ARegion *region, uiBut *but, c
return BLI_rcti_isect_pt(&icon_rect, x, y);
}
+static int ui_do_but_TAB(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if ((event->type == LEFTMOUSE) &&
+ ((event->val == KM_DBL_CLICK) || event->ctrl))
+ {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && (event->val == KM_CLICK)) {
+ const bool has_icon_extra = ui_but_icon_extra_get(but) == UI_BUT_ICONEXTRA_CLEAR;
+
+ if (has_icon_extra && ui_but_is_mouse_over_icon_extra(data->region, but, &event->x)) {
+ uiButTab *tab = (uiButTab *)but;
+ wmOperatorType *ot_backup = but->optype;
+
+ but->optype = tab->unlink_ot;
+ /* Force calling unlink/delete operator. */
+ ui_apply_but(C, block, but, data, true);
+ but->optype = ot_backup;
+ }
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_TEXT_EDITING) {
+ ui_do_but_textedit(C, block, but, data, event);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (data->state == BUTTON_STATE_TEXT_SELECTING) {
+ ui_do_but_textedit_select(C, block, but, data, event);
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
static int ui_do_but_TEX(
bContext *C, uiBlock *block, uiBut *but,
uiHandleButtonData *data, const wmEvent *event)
@@ -4375,6 +4218,54 @@ static bool ui_numedit_but_NUM(
return changed;
}
+static void ui_numedit_set_active(uiBut *but)
+{
+ int oldflag = but->drawflag;
+ but->drawflag &= ~(UI_BUT_ACTIVE_LEFT | UI_BUT_ACTIVE_RIGHT);
+
+ uiHandleButtonData *data = but->active;
+ if (!data) {
+ return;
+ }
+
+ /* Ignore once we start dragging. */
+ if (data->dragchange == false) {
+ const float handle_width = min_ff(BLI_rctf_size_x(&but->rect) / 3, BLI_rctf_size_y(&but->rect) * 0.7f);
+ /* we can click on the side arrows to increment/decrement,
+ * or click inside to edit the value directly */
+ int mx = data->window->eventstate->x;
+ int my = data->window->eventstate->x;
+ ui_window_to_block(data->region, but->block, &mx, &my);
+
+ if (mx < (but->rect.xmin + handle_width)) {
+ but->drawflag |= UI_BUT_ACTIVE_LEFT;
+ }
+ else if (mx > (but->rect.xmax - handle_width)) {
+ but->drawflag |= UI_BUT_ACTIVE_RIGHT;
+ }
+ }
+
+ /* Don't change the cursor once pressed. */
+ if ((but->flag & UI_SELECT) == 0) {
+ if ((but->drawflag & (UI_BUT_ACTIVE_LEFT)) || (but->drawflag & (UI_BUT_ACTIVE_RIGHT))) {
+ if (data->changed_cursor) {
+ WM_cursor_modal_restore(data->window);
+ data->changed_cursor = false;
+ }
+ }
+ else {
+ if (data->changed_cursor == false) {
+ WM_cursor_modal_set(data->window, CURSOR_X_MOVE);
+ data->changed_cursor = true;
+ }
+ }
+ }
+
+ if (but->drawflag != oldflag) {
+ ED_region_tag_redraw(data->region);
+ }
+}
+
static int ui_do_but_NUM(
bContext *C, uiBlock *block, uiBut *but,
uiHandleButtonData *data, const wmEvent *event)
@@ -4388,6 +4279,7 @@ static int ui_do_but_NUM(
my = screen_my = event->y;
ui_window_to_block(data->region, block, &mx, &my);
+ ui_numedit_set_active(but);
if (data->state == BUTTON_STATE_HIGHLIGHT) {
int type = event->type, val = event->val;
@@ -4401,10 +4293,14 @@ static int ui_do_but_NUM(
retval = WM_UI_HANDLER_BREAK; /* allow accumulating values, otherwise scrolling gets preference */
else if (type == WHEELDOWNMOUSE && event->ctrl) {
mx = but->rect.xmin;
+ but->drawflag &= ~UI_BUT_ACTIVE_RIGHT;
+ but->drawflag |= UI_BUT_ACTIVE_LEFT;
click = 1;
}
else if (type == WHEELUPMOUSE && event->ctrl) {
mx = but->rect.xmax;
+ but->drawflag &= ~UI_BUT_ACTIVE_LEFT;
+ but->drawflag |= UI_BUT_ACTIVE_RIGHT;
click = 1;
}
else if (event->val == KM_PRESS) {
@@ -4497,16 +4393,13 @@ static int ui_do_but_NUM(
/* we can click on the side arrows to increment/decrement,
* or click inside to edit the value directly */
float tempf, softmin, softmax;
- float handlewidth;
int temp;
softmin = but->softmin;
softmax = but->softmax;
- handlewidth = min_ff(BLI_rctf_size_x(&but->rect) / 3, BLI_rctf_size_y(&but->rect));
-
if (!ui_but_is_float(but)) {
- if (mx < (but->rect.xmin + handlewidth)) {
+ if (but->drawflag & UI_BUT_ACTIVE_LEFT) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
temp = (int)data->value - 1;
@@ -4517,7 +4410,7 @@ static int ui_do_but_NUM(
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
- else if (mx > (but->rect.xmax - handlewidth)) {
+ else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
temp = (int)data->value + 1;
@@ -4533,7 +4426,7 @@ static int ui_do_but_NUM(
}
}
else {
- if (mx < (but->rect.xmin + handlewidth)) {
+ if (but->drawflag & UI_BUT_ACTIVE_LEFT) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
tempf = (float)data->value - (UI_PRECISION_FLOAT_SCALE * but->a1);
@@ -4542,7 +4435,7 @@ static int ui_do_but_NUM(
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
- else if (mx > but->rect.xmax - handlewidth) {
+ else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
tempf = (float)data->value + (UI_PRECISION_FLOAT_SCALE * but->a1);
@@ -5265,7 +5158,8 @@ static int ui_do_but_COLOR(
if (!event->ctrl) {
float color[3];
Scene *scene = CTX_data_scene(C);
- Paint *paint = BKE_paint_get_active(scene);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Paint *paint = BKE_paint_get_active(scene, view_layer);
Brush *brush = BKE_paint_brush(paint);
if (brush->flag & BRUSH_USE_GRADIENT) {
@@ -6182,6 +6076,7 @@ static int ui_do_but_CURVE(
int mx, my, a;
bool changed = false;
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
mx = event->x;
my = event->y;
@@ -6310,7 +6205,7 @@ static int ui_do_but_CURVE(
}
else {
curvemapping_changed(cumap, true); /* remove doubles */
- BKE_paint_invalidate_cursor_overlay(scene, cumap);
+ BKE_paint_invalidate_cursor_overlay(scene, view_layer, cumap);
}
}
@@ -6476,35 +6371,6 @@ static int ui_do_but_WAVEFORM(
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_LINK(
- bContext *C, uiBut *but,
- uiHandleButtonData *data, const wmEvent *event)
-{
- VECCOPY2D(but->linkto, event->mval);
-
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
- button_activate_state(C, but, BUTTON_STATE_WAIT_RELEASE);
- return WM_UI_HANDLER_BREAK;
- }
- else if (event->type == LEFTMOUSE && but->block->handle) {
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- return WM_UI_HANDLER_BREAK;
- }
- }
- else if (data->state == BUTTON_STATE_WAIT_RELEASE) {
-
- if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
- if (!(but->flag & UI_SELECT))
- data->cancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- return WM_UI_HANDLER_BREAK;
- }
- }
-
- return WM_UI_HANDLER_CONTINUE;
-}
-
static bool ui_numedit_but_TRACKPREVIEW(
bContext *C, uiBut *but, uiHandleButtonData *data,
int mx, int my,
@@ -6648,6 +6514,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case UI_BTYPE_HOTKEY_EVENT:
retval = ui_do_but_HOTKEYEVT(C, but, data, event);
break;
+ case UI_BTYPE_TAB:
+ retval = ui_do_but_TAB(C, block, but, data, event);
+ break;
case UI_BTYPE_BUT_TOGGLE:
case UI_BTYPE_TOGGLE:
case UI_BTYPE_ICON_TOGGLE:
@@ -6705,6 +6574,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
retval = ui_do_but_TEX(C, block, but, data, event);
break;
case UI_BTYPE_MENU:
+ case UI_BTYPE_POPOVER:
case UI_BTYPE_BLOCK:
case UI_BTYPE_PULLDOWN:
retval = ui_do_but_BLOCK(C, but, data, event);
@@ -6733,10 +6603,6 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case UI_BTYPE_HSVCIRCLE:
retval = ui_do_but_HSVCIRCLE(C, block, but, data, event);
break;
- case UI_BTYPE_LINK:
- case UI_BTYPE_INLINK:
- retval = ui_do_but_LINK(C, but, data, event);
- break;
case UI_BTYPE_TRACK_PREVIEW:
retval = ui_do_but_TRACKPREVIEW(C, block, but, data, event);
break;
@@ -6744,6 +6610,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
/* quiet warnings for unhandled types */
case UI_BTYPE_SEPR:
case UI_BTYPE_SEPR_LINE:
+ case UI_BTYPE_SEPR_SPACER:
case UI_BTYPE_EXTRA:
break;
}
@@ -6920,12 +6787,11 @@ bool ui_but_is_active(ARegion *ar)
/* is called by notifier */
void UI_screen_free_active_but(const bContext *C, bScreen *screen)
{
- ScrArea *sa = screen->areabase.first;
+ wmWindow *win = CTX_wm_window(C);
- for (; sa; sa = sa->next) {
- ARegion *ar = sa->regionbase.first;
- for (; ar; ar = ar->next) {
- uiBut *but = ui_but_find_active_in_region(ar);
+ ED_screen_areas_iter(win, screen, area) {
+ for (ARegion *region = area->regionbase.first; region; region = region->next) {
+ uiBut *but = ui_but_find_active_in_region(region);
if (but) {
uiHandleButtonData *data = but->active;
@@ -7011,7 +6877,7 @@ static bool ui_region_contains_point_px(ARegion *ar, int x, int y)
ui_window_to_region(ar, &mx, &my);
/* check if in the rect */
- if (!BLI_rcti_isect_pt(&v2d->mask, mx, my)) {
+ if (!BLI_rcti_isect_pt(&v2d->mask, mx, my) || UI_view2d_mouse_in_scrollers(ar, &ar->v2d, x, y)) {
return false;
}
}
@@ -7166,7 +7032,7 @@ void UI_but_tooltip_refresh(bContext *C, uiBut *but)
{
uiHandleButtonData *data = but->active;
if (data) {
- bScreen *sc = data->window->screen;
+ bScreen *sc = WM_window_get_active_screen(data->window);
if (sc->tool_tip && sc->tool_tip->region) {
WM_tooltip_refresh(C, data->window);
}
@@ -7232,7 +7098,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
button_tooltip_timer_reset(C, but);
/* automatic open pulldown block timer */
- if (ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN)) {
+ if (ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) {
if (data->used_mouse && !data->autoopentimer) {
int time;
@@ -7442,6 +7308,9 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
const bool horizontal = (BLI_rctf_size_x(&but->rect) < BLI_rctf_size_y(&but->rect));
WM_cursor_modal_set(data->window, horizontal ? CURSOR_X_MOVE : CURSOR_Y_MOVE);
}
+ else if (but->type == UI_BTYPE_NUM) {
+ ui_numedit_set_active(but);
+ }
}
static void button_activate_exit(
@@ -7535,8 +7404,13 @@ static void button_activate_exit(
ui_selectcontext_end(but, &data->select_others);
#endif
- /* redraw (data is but->active!) */
+ if (data->changed_cursor) {
+ WM_cursor_modal_restore(data->window);
+ }
+
+ /* redraw and refresh (for popups) */
ED_region_tag_redraw(data->region);
+ ED_region_tag_refresh_ui(data->region);
/* clean up button */
if (but->active) {
@@ -7722,6 +7596,11 @@ void UI_context_update_anim_flag(const bContext *C)
for (block = ar->uiblocks.first; block; block = block->next) {
for (but = block->buttons.first; but; but = but->next) {
ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f);
+ ui_but_override_flag(but);
+ if (UI_but_is_decorator(but)) {
+ ui_but_anim_decorate_update_from_flag(but);
+ }
+
ED_region_tag_redraw(ar);
if (but->active) {
@@ -7909,8 +7788,29 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
case EVT_BUT_CANCEL:
data->cancel = true;
button_activate_state(C, but, BUTTON_STATE_EXIT);
- retval = WM_UI_HANDLER_CONTINUE;
break;
+#ifdef USE_UI_POPOVER_ONCE
+ case LEFTMOUSE:
+ {
+ if (event->val == KM_RELEASE) {
+ if (block->flag & UI_BLOCK_POPOVER_ONCE) {
+ if (!(but->flag & UI_BUT_DISABLED)) {
+ if (ui_but_is_popover_once_compat(but)) {
+ data->cancel = false;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ retval = WM_UI_HANDLER_BREAK;
+ block->handle->menuretval = UI_RETURN_OK;
+ }
+ else if (ui_but_is_editable_as_text(but)) {
+ ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_TEXT_EDITING);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+ }
+ break;
+ }
+#endif
case MOUSEMOVE:
{
uiBut *but_other = ui_but_find_mouse_over(ar, event);
@@ -7949,7 +7849,6 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
}
- retval = WM_UI_HANDLER_CONTINUE;
break;
}
/* XXX hardcoded keymap check... but anyway, while view changes, tooltips should be removed */
@@ -7960,10 +7859,11 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
UI_but_tooltip_timer_remove(C, but);
ATTR_FALLTHROUGH;
default:
- /* handle button type specific events */
- retval = ui_do_button(C, block, but, event);
break;
}
+
+ /* handle button type specific events */
+ retval = ui_do_button(C, block, but, event);
}
else if (data->state == BUTTON_STATE_WAIT_RELEASE) {
switch (event->type) {
@@ -7992,12 +7892,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
break;
}
case MOUSEMOVE:
- if (ELEM(but->type, UI_BTYPE_LINK, UI_BTYPE_INLINK)) {
- but->flag |= UI_SELECT;
- ui_do_button(C, block, but, event);
- ED_region_tag_redraw(ar);
- }
- else {
+ {
/* deselect the button when moving the mouse away */
/* also de-activate for buttons that only show higlights */
if (ui_but_contains_point_px(ar, but, event->x, event->y)) {
@@ -8260,13 +8155,8 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar,
}
if (redraw) {
- if (listbox->block->flag & UI_BLOCK_POPUP) {
- /* popups need special refreshing */
- ED_region_tag_refresh_ui(ar);
- }
- else {
- ED_region_tag_redraw(ar);
- }
+ ED_region_tag_redraw(ar);
+ ED_region_tag_refresh_ui(ar);
}
return retval;
@@ -8525,6 +8415,9 @@ static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my, uiBut *to_bt)
dy = block->rect.ymin - ymin + UI_MENU_SCROLL_PAD;
}
+ /* remember scroll offset for refreshes */
+ block->handle->scrolloffset += dy;
+
/* apply scroll offset */
for (bt = block->buttons.first; bt; bt = bt->next) {
bt->rect.ymin += dy;
@@ -8677,7 +8570,7 @@ static int ui_handle_menu_event(
add_v2_v2v2_int(menu->popup_create_vars.event_xy, menu->popup_create_vars.event_xy, mdiff);
- ui_popup_translate(C, ar, mdiff);
+ ui_popup_translate(ar, mdiff);
}
return retval;
@@ -9061,6 +8954,15 @@ static int ui_handle_menu_event(
retval = ui_handle_menu_button(C, event, menu);
}
+#ifdef USE_UI_POPOVER_ONCE
+ if (block->flag & UI_BLOCK_POPOVER_ONCE) {
+ if ((event->type == LEFTMOUSE) && (event->val == KM_RELEASE)) {
+ UI_popover_once_clear(menu->popup_create_vars.arg);
+ block->flag &= ~UI_BLOCK_POPOVER_ONCE;
+ }
+ }
+#endif
+
/* Don't handle double click events, rehandle as regular press/release. */
if (retval == WM_UI_HANDLER_CONTINUE && event->val == KM_DBL_CLICK) {
return retval;
@@ -9680,10 +9582,10 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE
if ((data->state == BUTTON_STATE_MENU_OPEN) &&
(is_inside_menu == false) && /* make sure mouse isn't inside another menu (see T43247) */
- (but->type == UI_BTYPE_PULLDOWN) &&
+ (ELEM(but->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) &&
(but_other = ui_but_find_mouse_over(ar, event)) &&
(but != but_other) &&
- (but->type == but_other->type))
+ (ELEM(but_other->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)))
{
/* if mouse moves to a different root-level menu button,
* open it to replace the current menu */
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index eed7f2ec0f2..62413e2434c 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -33,12 +33,16 @@
#include "MEM_guardedalloc.h"
-#include "GPU_extensions.h"
-#include "GPU_basic_shader.h"
+#include "GPU_draw.h"
+#include "GPU_matrix.h"
+#include "GPU_batch.h"
+#include "GPU_immediate.h"
+#include "GPU_state.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
+#include "BLI_math_vector.h"
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
@@ -46,6 +50,7 @@
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
+#include "DNA_workspace_types.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
@@ -54,14 +59,18 @@
#include "BKE_global.h"
#include "BKE_icons.h"
#include "BKE_appdir.h"
+#include "BKE_studiolight.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_thumbs.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "DEG_depsgraph.h"
+
+#include "DRW_engine.h"
+
#include "ED_datafiles.h"
#include "ED_keyframes_draw.h"
#include "ED_render.h"
@@ -69,6 +78,9 @@
#include "UI_interface.h"
#include "UI_interface_icons.h"
+#include "WM_api.h"
+#include "WM_types.h"
+
#include "interface_intern.h"
#ifndef WITH_HEADLESS
@@ -90,10 +102,13 @@ typedef struct IconImage {
typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
-#define ICON_TYPE_PREVIEW 0
-#define ICON_TYPE_TEXTURE 1
-#define ICON_TYPE_BUFFER 2
-#define ICON_TYPE_VECTOR 3
+#define ICON_TYPE_PREVIEW 0
+#define ICON_TYPE_TEXTURE 1
+#define ICON_TYPE_MONO_TEXTURE 2
+#define ICON_TYPE_BUFFER 3
+#define ICON_TYPE_VECTOR 4
+#define ICON_TYPE_GEOM 5
+#define ICON_TYPE_EVENT 6 /* draw keymap entries using custom renderer. */
typedef struct DrawInfo {
int type;
@@ -104,11 +119,22 @@ typedef struct DrawInfo {
VectorDrawFunc func;
} vector;
struct {
+ ImBuf *image_cache;
+ } geom;
+ struct {
IconImage *image;
} buffer;
struct {
int x, y, w, h;
} texture;
+ struct {
+ /* Can be packed into a single int. */
+ short event_type;
+ short event_value;
+ int icon;
+ /* Allow lookups. */
+ struct DrawInfo *next;
+ } input;
} data;
} DrawInfo;
@@ -144,7 +170,7 @@ static DrawInfo *def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs,
di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
di->type = type;
- if (type == ICON_TYPE_TEXTURE) {
+ if (ELEM(type, ICON_TYPE_TEXTURE, ICON_TYPE_MONO_TEXTURE)) {
di->data.texture.x = xofs;
di->data.texture.y = yofs;
di->data.texture.w = size;
@@ -224,13 +250,17 @@ static void vicon_small_tri_right_draw(int x, int y, int w, int UNUSED(h), float
viconutil_set_point(pts[1], cx - d2, cy - d);
viconutil_set_point(pts[2], cx + d2, cy);
- glColor4f(0.2f, 0.2f, 0.2f, alpha);
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(0.2f, 0.2f, 0.2f, alpha);
+
+ immBegin(GWN_PRIM_TRIS, 3);
+ immVertex2iv(pos, pts[0]);
+ immVertex2iv(pos, pts[1]);
+ immVertex2iv(pos, pts[2]);
+ immEnd();
- glBegin(GL_TRIANGLES);
- glVertex2iv(pts[0]);
- glVertex2iv(pts[1]);
- glVertex2iv(pts[2]);
- glEnd();
+ immUnbindProgram();
}
static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha, short key_type)
@@ -239,7 +269,6 @@ static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha,
* (since we're doing this offscreen, free from any particular space_id)
*/
struct bThemeState theme_state;
- int xco, yco;
UI_Theme_Store(&theme_state);
UI_SetTheme(SPACE_ACTION, RGN_TYPE_WINDOW);
@@ -248,15 +277,29 @@ static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha,
* while the draw_keyframe_shape() function needs the midpoint for
* the keyframe
*/
- xco = x + w / 2;
- yco = y + h / 2;
+ int xco = x + w / 2;
+ int yco = y + h / 2;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ uint color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ uint outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ GPU_enable_program_point_size();
+ immBegin(GWN_PRIM_POINTS, 1);
/* draw keyframe
- * - xscale: 1.0 (since there's no timeline scaling to compensate for)
- * - yscale: 0.3 * h (found out experimentally... dunno why!)
+ * - size: 0.6 * h (found out experimentally... dunno why!)
* - sel: true (so that "keyframe" state shows the iconic yellow icon)
*/
- draw_keyframe_shape(xco, yco, 1.0f, 0.3f * h, true, key_type, KEYFRAME_SHAPE_BOTH, alpha);
+ draw_keyframe_shape(xco, yco, 0.6f * h, true, key_type, KEYFRAME_SHAPE_BOTH, alpha,
+ pos_id, size_id, color_id, outline_color_id);
+
+ immEnd();
+ GPU_disable_program_point_size();
+ immUnbindProgram();
UI_Theme_Restore(&theme_state);
}
@@ -300,18 +343,23 @@ static void vicon_colorset_draw(int index, int x, int y, int w, int h, float UNU
const int b = x + w / 3 * 2;
const int c = x + w;
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* XXX: Include alpha into this... */
/* normal */
- glColor3ubv((unsigned char *)cs->solid);
- glRecti(x, y, a, y + h);
+ immUniformColor3ubv((unsigned char *)cs->solid);
+ immRecti(pos, x, y, a, y + h);
/* selected */
- glColor3ubv((unsigned char *)cs->select);
- glRecti(a, y, b, y + h);
+ immUniformColor3ubv((unsigned char *)cs->select);
+ immRecti(pos, a, y, b, y + h);
/* active */
- glColor3ubv((unsigned char *)cs->active);
- glRecti(b, y, c, y + h);
+ immUniformColor3ubv((unsigned char *)cs->active);
+ immRecti(pos, b, y, c, y + h);
+
+ immUnbindProgram();
}
#define DEF_VICON_COLORSET_DRAW_NTH(prefix, index) \
@@ -398,6 +446,143 @@ static void init_brush_icons(void)
#undef INIT_BRUSH_ICON
}
+static DrawInfo *g_di_event_list = NULL;
+
+int UI_icon_from_event_type(short event_type, short event_value)
+{
+ if (event_type == RIGHTSHIFTKEY) {
+ event_type = LEFTSHIFTKEY;
+ }
+ else if (event_type == RIGHTCTRLKEY) {
+ event_type = LEFTCTRLKEY;
+ }
+ else if (event_type == RIGHTALTKEY) {
+ event_type = LEFTALTKEY;
+ }
+ else if (event_type == EVT_TWEAK_L) {
+ event_type = LEFTMOUSE;
+ event_value = KM_CLICK_DRAG;
+ }
+ else if (event_type == EVT_TWEAK_M) {
+ event_type = MIDDLEMOUSE;
+ event_value = KM_CLICK_DRAG;
+ }
+ else if (event_type == EVT_TWEAK_R) {
+ event_type = RIGHTMOUSE;
+ event_value = KM_CLICK_DRAG;
+ }
+
+ DrawInfo *di = g_di_event_list;
+ do {
+ if (di->data.input.event_type == event_type) {
+ return di->data.input.icon;
+ }
+ } while ((di = di->data.input.next));
+
+ if (event_type == LEFTMOUSE) {
+ return ELEM(event_value, KM_CLICK, KM_PRESS) ? ICON_MOUSE_LMB : ICON_MOUSE_LMB_DRAG;
+ }
+ else if (event_type == MIDDLEMOUSE) {
+ return ELEM(event_value, KM_CLICK, KM_PRESS) ? ICON_MOUSE_MMB : ICON_MOUSE_MMB_DRAG;
+ }
+ else if (event_type == RIGHTMOUSE) {
+ return ELEM(event_value, KM_CLICK, KM_PRESS) ? ICON_MOUSE_RMB : ICON_MOUSE_RMB_DRAG;
+ }
+
+ return ICON_NONE;
+}
+
+int UI_icon_from_keymap_item(const wmKeyMapItem *kmi, int r_icon_mod[4])
+{
+ if (r_icon_mod) {
+ memset(r_icon_mod, 0x0, sizeof(int[4]));
+ int i = 0;
+ if (!ELEM(kmi->ctrl, KM_NOTHING, KM_ANY)) {
+ r_icon_mod[i++] = ICON_EVENT_CTRL;
+ }
+ if (!ELEM(kmi->alt, KM_NOTHING, KM_ANY)) {
+ r_icon_mod[i++] = ICON_EVENT_ALT;
+ }
+ if (!ELEM(kmi->shift, KM_NOTHING, KM_ANY)) {
+ r_icon_mod[i++] = ICON_EVENT_SHIFT;
+ }
+ if (!ELEM(kmi->oskey, KM_NOTHING, KM_ANY)) {
+ r_icon_mod[i++] = ICON_EVENT_OS;
+ }
+ }
+ return UI_icon_from_event_type(kmi->type, kmi->val);
+}
+
+static void init_event_icons(void)
+{
+ DrawInfo *di_next = NULL;
+
+#define INIT_EVENT_ICON(icon_id, type, value) \
+ { \
+ DrawInfo *di = def_internal_icon(NULL, icon_id, 0, 0, w, ICON_TYPE_EVENT); \
+ di->data.input.event_type = type; \
+ di->data.input.event_value = value; \
+ di->data.input.icon = icon_id; \
+ di->data.input.next = di_next; \
+ di_next = di; \
+ }
+ /* end INIT_EVENT_ICON */
+
+ const int w = 16; /* DUMMY */
+
+ INIT_EVENT_ICON(ICON_EVENT_A, AKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_B, BKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_C, CKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_D, DKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_E, EKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F, FKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_G, GKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_H, HKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_I, IKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_J, JKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_K, KKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_L, LKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_M, MKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_N, NKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_O, OKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_P, PKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_Q, QKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_R, RKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_S, SKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_T, TKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_U, UKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_V, VKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_W, WKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_X, XKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_Y, YKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_Z, ZKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_SHIFT, LEFTSHIFTKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_CTRL, LEFTCTRLKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_ALT, LEFTALTKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_OS, OSKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F1, F1KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F2, F2KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F3, F3KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F4, F4KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F5, F5KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F6, F6KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F7, F7KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F8, F8KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F9, F9KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F10, F10KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F11, F11KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_F12, F12KEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_ESC, ESCKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_TAB, TABKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_PAGEUP, PAGEUPKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_PAGEDOWN, PAGEDOWNKEY, KM_ANY);
+ INIT_EVENT_ICON(ICON_EVENT_RETURN, RETKEY, KM_ANY);
+
+ g_di_event_list = di_next;
+
+#undef INIT_EVENT_ICON
+}
+
static void icon_verify_datatoc(IconImage *iimg)
{
/* if it has own rect, things are all OK */
@@ -417,54 +602,11 @@ static void icon_verify_datatoc(IconImage *iimg)
}
}
-static void init_matcap_icons(void)
-{
- /* dynamic allocation now, tucking datatoc pointers in DrawInfo */
-#define INIT_MATCAP_ICON(icon_id, name) \
- { \
- unsigned char *rect = (unsigned char *)datatoc_ ##name## _jpg; \
- int size = datatoc_ ##name## _jpg_size; \
- DrawInfo *di; \
- \
- di = def_internal_icon(NULL, icon_id, 0, 0, 96, ICON_TYPE_BUFFER); \
- di->data.buffer.image->datatoc_rect = rect; \
- di->data.buffer.image->datatoc_size = size; \
- } (void)0
-
- INIT_MATCAP_ICON(ICON_MATCAP_01, mc01);
- INIT_MATCAP_ICON(ICON_MATCAP_02, mc02);
- INIT_MATCAP_ICON(ICON_MATCAP_03, mc03);
- INIT_MATCAP_ICON(ICON_MATCAP_04, mc04);
- INIT_MATCAP_ICON(ICON_MATCAP_05, mc05);
- INIT_MATCAP_ICON(ICON_MATCAP_06, mc06);
- INIT_MATCAP_ICON(ICON_MATCAP_07, mc07);
- INIT_MATCAP_ICON(ICON_MATCAP_08, mc08);
- INIT_MATCAP_ICON(ICON_MATCAP_09, mc09);
- INIT_MATCAP_ICON(ICON_MATCAP_10, mc10);
- INIT_MATCAP_ICON(ICON_MATCAP_11, mc11);
- INIT_MATCAP_ICON(ICON_MATCAP_12, mc12);
- INIT_MATCAP_ICON(ICON_MATCAP_13, mc13);
- INIT_MATCAP_ICON(ICON_MATCAP_14, mc14);
- INIT_MATCAP_ICON(ICON_MATCAP_15, mc15);
- INIT_MATCAP_ICON(ICON_MATCAP_16, mc16);
- INIT_MATCAP_ICON(ICON_MATCAP_17, mc17);
- INIT_MATCAP_ICON(ICON_MATCAP_18, mc18);
- INIT_MATCAP_ICON(ICON_MATCAP_19, mc19);
- INIT_MATCAP_ICON(ICON_MATCAP_20, mc20);
- INIT_MATCAP_ICON(ICON_MATCAP_21, mc21);
- INIT_MATCAP_ICON(ICON_MATCAP_22, mc22);
- INIT_MATCAP_ICON(ICON_MATCAP_23, mc23);
- INIT_MATCAP_ICON(ICON_MATCAP_24, mc24);
-
-#undef INIT_MATCAP_ICON
-
-}
-
static void init_internal_icons(void)
{
// bTheme *btheme = UI_GetTheme();
ImBuf *b16buf = NULL, *b32buf = NULL;
- int x, y, icontype;
+ int x, y;
#if 0 // temp disabled
if ((btheme != NULL) && btheme->tui.iconfile[0]) {
@@ -498,57 +640,46 @@ static void init_internal_icons(void)
IMB_premultiply_alpha(b32buf);
if (b16buf && b32buf) {
- /* free existing texture if any */
+ /* Free existing texture if any. */
if (icongltex.id) {
glDeleteTextures(1, &icongltex.id);
icongltex.id = 0;
}
- /* we only use a texture for cards with non-power of two */
- if (GPU_full_non_power_of_two_support()) {
- glGenTextures(1, &icongltex.id);
+ /* Allocate OpenGL texture. */
+ glGenTextures(1, &icongltex.id);
- if (icongltex.id) {
- int level = 2;
-
- icongltex.w = b32buf->x;
- icongltex.h = b32buf->y;
- icongltex.invw = 1.0f / b32buf->x;
- icongltex.invh = 1.0f / b32buf->y;
+ if (icongltex.id) {
+ int level = 2;
- glBindTexture(GL_TEXTURE_2D, icongltex.id);
+ icongltex.w = b32buf->x;
+ icongltex.h = b32buf->y;
+ icongltex.invw = 1.0f / b32buf->x;
+ icongltex.invh = 1.0f / b32buf->y;
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, b32buf->x, b32buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b32buf->rect);
- glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, b16buf->x, b16buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b16buf->rect);
+ glBindTexture(GL_TEXTURE_2D, icongltex.id);
- while (b16buf->x > 1) {
- ImBuf *nbuf = IMB_onehalf(b16buf);
- glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, nbuf->x, nbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nbuf->rect);
- level++;
- IMB_freeImBuf(b16buf);
- b16buf = nbuf;
- }
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, b32buf->x, b32buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b32buf->rect);
+ glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, b16buf->x, b16buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b16buf->rect);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ while (b16buf->x > 1) {
+ ImBuf *nbuf = IMB_onehalf(b16buf);
+ glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, nbuf->x, nbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nbuf->rect);
+ level++;
+ IMB_freeImBuf(b16buf);
+ b16buf = nbuf;
+ }
- glBindTexture(GL_TEXTURE_2D, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- if (glGetError() == GL_OUT_OF_MEMORY) {
- glDeleteTextures(1, &icongltex.id);
- icongltex.id = 0;
- }
- }
+ glBindTexture(GL_TEXTURE_2D, 0);
}
- }
-
- if (icongltex.id)
- icontype = ICON_TYPE_TEXTURE;
- else
- icontype = ICON_TYPE_BUFFER;
- if (b32buf) {
+ /* Define icons. */
for (y = 0; y < ICON_GRID_ROWS; y++) {
+ /* Row W has monochrome icons. */
+ int icontype = (y == 8) ? ICON_TYPE_MONO_TEXTURE : ICON_TYPE_TEXTURE;
for (x = 0; x < ICON_GRID_COLS; x++) {
def_internal_icon(b32buf, BIFICONID_FIRST + y * ICON_GRID_COLS + x,
x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
@@ -717,21 +848,53 @@ void UI_icons_free_drawinfo(void *drawinfo)
MEM_freeN(di->data.buffer.image);
}
}
+ else if (di->type == ICON_TYPE_GEOM) {
+ if (di->data.geom.image_cache) {
+ IMB_freeImBuf(di->data.geom.image_cache);
+ }
+ }
MEM_freeN(di);
}
}
-static DrawInfo *icon_create_drawinfo(void)
+/**
+ * #Icon.data_type and #Icon.obj
+ */
+static DrawInfo *icon_create_drawinfo(Icon *icon)
{
+ int icon_data_type = icon->obj_type;
DrawInfo *di = NULL;
di = MEM_callocN(sizeof(DrawInfo), "di_icon");
- di->type = ICON_TYPE_PREVIEW;
+
+ if (ELEM(icon_data_type, ICON_DATA_ID, ICON_DATA_PREVIEW)) {
+ di->type = ICON_TYPE_PREVIEW;
+ }
+ else if (icon_data_type == ICON_DATA_GEOM) {
+ di->type = ICON_TYPE_GEOM;
+ }
+ else if (icon_data_type == ICON_DATA_STUDIOLIGHT) {
+ di->type = ICON_TYPE_BUFFER;
+ }
+ else {
+ BLI_assert(0);
+ }
return di;
}
+static DrawInfo *icon_ensure_drawinfo(Icon *icon)
+{
+ if (icon->drawinfo) {
+ return icon->drawinfo;
+ }
+ DrawInfo *di = icon_create_drawinfo(icon);
+ icon->drawinfo = di;
+ icon->drawinfo_free = UI_icons_free_drawinfo;
+ return di;
+}
+
/* note!, returns unscaled by DPI */
int UI_icon_get_width(int icon_id)
{
@@ -746,40 +909,27 @@ int UI_icon_get_width(int icon_id)
return 0;
}
- di = (DrawInfo *)icon->drawinfo;
- if (!di) {
- di = icon_create_drawinfo();
- icon->drawinfo = di;
- }
-
- if (di)
+ di = icon_ensure_drawinfo(icon);
+ if (di) {
return ICON_DEFAULT_WIDTH;
+ }
return 0;
}
int UI_icon_get_height(int icon_id)
{
- Icon *icon = NULL;
- DrawInfo *di = NULL;
-
- icon = BKE_icon_get(icon_id);
-
+ Icon *icon = BKE_icon_get(icon_id);
if (icon == NULL) {
if (G.debug & G_DEBUG)
printf("%s: Internal error, no icon for icon ID: %d\n", __func__, icon_id);
return 0;
}
- di = (DrawInfo *)icon->drawinfo;
-
- if (!di) {
- di = icon_create_drawinfo();
- icon->drawinfo = di;
- }
-
- if (di)
+ DrawInfo *di = icon_ensure_drawinfo(icon);
+ if (di) {
return ICON_DEFAULT_HEIGHT;
+ }
return 0;
}
@@ -791,7 +941,7 @@ void UI_icons_init(int first_dyn_id)
init_iconfile_list(&iconfilelist);
init_internal_icons();
init_brush_icons();
- init_matcap_icons();
+ init_event_icons();
#endif
}
@@ -831,19 +981,47 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
static void ui_id_preview_image_render_size(
const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job);
-void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool big)
+static void ui_studiolight_icon_job_exec(void *customdata, short *UNUSED(stop), short *UNUSED(do_update), float *UNUSED(progress))
+{
+ Icon **tmp = (Icon **)customdata;
+ Icon *icon = *tmp;
+ DrawInfo *di = icon_ensure_drawinfo(icon);
+ StudioLight *sl = icon->obj;
+ BKE_studiolight_preview(di->data.buffer.image->rect, sl, icon->id_type);
+}
+
+static void ui_studiolight_kill_icon_preview_job(wmWindowManager *wm, int icon_id)
{
Icon *icon = BKE_icon_get(icon_id);
+ WM_jobs_kill_type(wm, icon, WM_JOB_TYPE_STUDIOLIGHT);
+ icon->obj = NULL;
+}
- if (icon) {
- DrawInfo *di = (DrawInfo *)icon->drawinfo;
+static void ui_studiolight_free_function(StudioLight *sl, void *data)
+{
+ wmWindowManager *wm = data;
- if (!di) {
- di = icon_create_drawinfo();
+ // get icons_id, get icons and kill wm jobs
+ if (sl->icon_id_radiance) {
+ ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_radiance);
+ }
+ if (sl->icon_id_irradiance) {
+ ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_irradiance);
+ }
+ if (sl->icon_id_matcap) {
+ ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_matcap);
+ }
+ if (sl->icon_id_matcap_flipped) {
+ ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_matcap_flipped);
+ }
+}
- icon->drawinfo = di;
- icon->drawinfo_free = UI_icons_free_drawinfo;
- }
+void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool big)
+{
+ Icon *icon = BKE_icon_get(icon_id);
+
+ if (icon) {
+ DrawInfo *di = icon_ensure_drawinfo(icon);
if (di) {
switch (di->type) {
@@ -851,12 +1029,42 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi
{
ID *id = (icon->id_type != 0) ? icon->obj : NULL;
PreviewImage *prv = id ? BKE_previewimg_id_ensure(id) : icon->obj;
+ /* Using jobs for screen previews crashes due to offscreen rendering.
+ * XXX would be nicer if PreviewImage could store if it supports jobs */
+ const bool use_jobs = !id || (GS(id->name) != ID_SCR);
if (prv) {
const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON;
if (id || (prv->tag & PRV_TAG_DEFFERED) != 0) {
- ui_id_preview_image_render_size(C, NULL, id, prv, size, true);
+ ui_id_preview_image_render_size(C, NULL, id, prv, size, use_jobs);
+ }
+ }
+ break;
+ }
+ case ICON_TYPE_BUFFER:
+ {
+ if (icon->obj_type == ICON_DATA_STUDIOLIGHT) {
+ if (di->data.buffer.image == NULL) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ StudioLight *sl = icon->obj;
+ BKE_studiolight_set_free_function(sl, &ui_studiolight_free_function, wm);
+ IconImage *img = MEM_mallocN(sizeof(IconImage), __func__);
+
+ img->w = STUDIOLIGHT_ICON_SIZE;
+ img->h = STUDIOLIGHT_ICON_SIZE;
+ size_t size = STUDIOLIGHT_ICON_SIZE * STUDIOLIGHT_ICON_SIZE * sizeof(uint);
+ img->rect = MEM_mallocN(size, __func__);
+ memset(img->rect, 0, size);
+ di->data.buffer.image = img;
+
+ wmJob *wm_job = WM_jobs_get(wm, CTX_wm_window(C), icon, "StudioLight Icon", 0, WM_JOB_TYPE_STUDIOLIGHT);
+ Icon **tmp = MEM_callocN(sizeof(Icon *), __func__);
+ *tmp = icon;
+ WM_jobs_customdata_set(wm_job, tmp, MEM_freeN);
+ WM_jobs_timer(wm_job, 0.01, 0, NC_WINDOW);
+ WM_jobs_callbacks(wm_job, ui_studiolight_icon_job_exec, NULL, NULL, NULL);
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
}
}
break;
@@ -936,7 +1144,7 @@ PreviewImage *UI_icon_to_preview(int icon_id)
}
static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh,
- unsigned int *rect, float alpha, const float rgb[3], const bool is_preview)
+ unsigned int *rect, float alpha, const float rgb[3], const float desaturate)
{
ImBuf *ima = NULL;
int draw_w = w;
@@ -950,15 +1158,13 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect),
BLI_assert(!"invalid icon size");
return;
}
-
/* modulate color */
- if (alpha != 1.0f)
- glPixelTransferf(GL_ALPHA_SCALE, alpha);
+ float col[4] = {1.0f, 1.0f, 1.0f, alpha};
if (rgb) {
- glPixelTransferf(GL_RED_SCALE, rgb[0]);
- glPixelTransferf(GL_GREEN_SCALE, rgb[1]);
- glPixelTransferf(GL_BLUE_SCALE, rgb[2]);
+ col[0] = rgb[0];
+ col[1] = rgb[1];
+ col[2] = rgb[2];
}
/* rect contains image in 'rendersize', we only scale if needed */
@@ -983,72 +1189,169 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect),
rect = ima->rect;
}
+ /* We need to flush widget base first to ensure correct ordering. */
+ UI_widgetbase_draw_cache_flush();
+
/* draw */
- if (is_preview) {
- glaDrawPixelsSafe(draw_x, draw_y, draw_w, draw_h, draw_w, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ GPUBuiltinShader shader;
+ if (desaturate != 0.0f) {
+ shader = GPU_SHADER_2D_IMAGE_DESATURATE_COLOR;
}
else {
- int bound_options;
- GPU_BASIC_SHADER_DISABLE_AND_STORE(bound_options);
-
- glRasterPos2f(draw_x, draw_y);
- glDrawPixels(draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ shader = GPU_SHADER_2D_IMAGE_COLOR;
+ }
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(shader);
- GPU_BASIC_SHADER_ENABLE_AND_RESTORE(bound_options);
+ if (shader == GPU_SHADER_2D_IMAGE_DESATURATE_COLOR) {
+ immUniform1f("factor", desaturate);
}
+ immDrawPixelsTex(&state, draw_x, draw_y, draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect,
+ 1.0f, 1.0f, col);
+
if (ima)
IMB_freeImBuf(ima);
+}
- /* restore color */
- if (alpha != 0.0f)
- glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
+/* High enough to make a difference, low enough so that
+ * small draws are still efficient with the use of glUniform.
+ * NOTE TODO: We could use UBO but we would need some triple
+ * buffer system + persistent mapping for this to be more
+ * efficient than simple glUniform calls. */
+#define ICON_DRAW_CACHE_SIZE 16
+
+typedef struct IconDrawCall {
+ rctf pos;
+ rctf tex;
+ float color[4];
+} IconDrawCall;
+
+static struct {
+ IconDrawCall drawcall_cache[ICON_DRAW_CACHE_SIZE];
+ int calls; /* Number of calls batched together */
+ bool enabled;
+ float mat[4][4];
+} g_icon_draw_cache = {{{{0}}}};
+
+void UI_icon_draw_cache_begin(void)
+{
+ BLI_assert(g_icon_draw_cache.enabled == false);
+ g_icon_draw_cache.enabled = true;
+}
- if (rgb) {
- glPixelTransferf(GL_RED_SCALE, 1.0f);
- glPixelTransferf(GL_GREEN_SCALE, 1.0f);
- glPixelTransferf(GL_BLUE_SCALE, 1.0f);
+static void icon_draw_cache_flush_ex(void)
+{
+ if (g_icon_draw_cache.calls == 0)
+ return;
+
+ /* We need to flush widget base first to ensure correct ordering. */
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ UI_widgetbase_draw_cache_flush();
+
+ GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, icongltex.id);
+
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR);
+ GPU_shader_bind(shader);
+
+ int img_loc = GPU_shader_get_uniform(shader, "image");
+ int data_loc = GPU_shader_get_uniform(shader, "calls_data[0]");
+
+ glUniform1i(img_loc, 0);
+ glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)g_icon_draw_cache.drawcall_cache);
+
+ GWN_draw_primitive(GWN_PRIM_TRIS, 6 * g_icon_draw_cache.calls);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ g_icon_draw_cache.calls = 0;
+}
+
+void UI_icon_draw_cache_end(void)
+{
+ BLI_assert(g_icon_draw_cache.enabled == true);
+ g_icon_draw_cache.enabled = false;
+
+ /* Don't change blend state if it's not needed. */
+ if (g_icon_draw_cache.calls == 0)
+ return;
+
+ GPU_blend(true);
+
+ icon_draw_cache_flush_ex();
+
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(false);
+}
+
+static void icon_draw_texture_cached(
+ float x, float y, float w, float h, int ix, int iy,
+ int UNUSED(iw), int ih, float alpha, const float rgb[3])
+{
+
+ float mvp[4][4];
+ gpuGetModelViewProjectionMatrix(mvp);
+
+ IconDrawCall *call = &g_icon_draw_cache.drawcall_cache[g_icon_draw_cache.calls];
+ g_icon_draw_cache.calls++;
+
+ /* Manual mat4*vec2 */
+ call->pos.xmin = x * mvp[0][0] + y * mvp[1][0] + mvp[3][0];
+ call->pos.ymin = x * mvp[0][1] + y * mvp[1][1] + mvp[3][1];
+ call->pos.xmax = call->pos.xmin + w * mvp[0][0] + h * mvp[1][0];
+ call->pos.ymax = call->pos.ymin + w * mvp[0][1] + h * mvp[1][1];
+
+ call->tex.xmin = ix * icongltex.invw;
+ call->tex.xmax = (ix + ih) * icongltex.invw;
+ call->tex.ymin = iy * icongltex.invh;
+ call->tex.ymax = (iy + ih) * icongltex.invh;
+
+ if (rgb) copy_v4_fl4(call->color, rgb[0], rgb[1], rgb[2], alpha);
+ else copy_v4_fl(call->color, alpha);
+
+ if (g_icon_draw_cache.calls == ICON_DRAW_CACHE_SIZE) {
+ icon_draw_cache_flush_ex();
}
}
static void icon_draw_texture(
float x, float y, float w, float h, int ix, int iy,
- int UNUSED(iw), int ih, float alpha, const float rgb[3])
+ int iw, int ih, float alpha, const float rgb[3])
{
- float x1, x2, y1, y2;
+ if (g_icon_draw_cache.enabled) {
+ icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb);
+ return;
+ }
- if (rgb) glColor4f(rgb[0], rgb[1], rgb[2], alpha);
- else glColor4f(alpha, alpha, alpha, alpha);
+ /* We need to flush widget base first to ensure correct ordering. */
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ UI_widgetbase_draw_cache_flush();
+
+ float x1, x2, y1, y2;
x1 = ix * icongltex.invw;
x2 = (ix + ih) * icongltex.invw;
y1 = iy * icongltex.invh;
y2 = (iy + ih) * icongltex.invh;
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
+ glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, icongltex.id);
- /* sharper downscaling, has no effect when scale matches with a mip level */
- glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -0.5f);
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
+ GPU_shader_bind(shader);
- glBegin(GL_QUADS);
- glTexCoord2f(x1, y1);
- glVertex2f(x, y);
+ if (rgb) glUniform4f(GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_COLOR), rgb[0], rgb[1], rgb[2], alpha);
+ else glUniform4f(GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_COLOR), alpha, alpha, alpha, alpha);
- glTexCoord2f(x2, y1);
- glVertex2f(x + w, y);
+ glUniform1i(GPU_shader_get_uniform(shader, "image"), 0);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), x1, y1, x2, y2);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), x, y, x + w, y + h);
- glTexCoord2f(x2, y2);
- glVertex2f(x + w, y + h);
-
- glTexCoord2f(x1, y2);
- glVertex2f(x, y + h);
- glEnd();
-
- glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0.0f);
+ GWN_draw_primitive(GWN_PRIM_TRI_STRIP, 4);
glBindTexture(GL_TEXTURE_2D, 0);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
/* Drawing size for preview images */
@@ -1068,11 +1371,10 @@ static int get_draw_size(enum eIconSizes size)
static void icon_draw_size(
float x, float y, int icon_id, float aspect, float alpha, const float rgb[3],
- enum eIconSizes size, int draw_size, const bool UNUSED(nocreate), const bool is_preview)
+ enum eIconSizes size, int draw_size, const float desaturate)
{
bTheme *btheme = UI_GetTheme();
Icon *icon = NULL;
- DrawInfo *di = NULL;
IconImage *iimg;
const float fdraw_size = (float)draw_size;
int w, h;
@@ -1086,31 +1388,77 @@ static void icon_draw_size(
return;
}
- di = (DrawInfo *)icon->drawinfo;
-
- if (!di) {
- di = icon_create_drawinfo();
-
- icon->drawinfo = di;
- icon->drawinfo_free = UI_icons_free_drawinfo;
- }
-
/* scale width and height according to aspect */
w = (int)(fdraw_size / aspect + 0.5f);
h = (int)(fdraw_size / aspect + 0.5f);
+ DrawInfo *di = icon_ensure_drawinfo(icon);
+
if (di->type == ICON_TYPE_VECTOR) {
+ /* We need to flush widget base first to ensure correct ordering. */
+ UI_widgetbase_draw_cache_flush();
/* vector icons use the uiBlock transformation, they are not drawn
* with untransformed coordinates like the other icons */
di->data.vector.func((int)x, (int)y, w, h, 1.0f);
}
+ else if (di->type == ICON_TYPE_GEOM) {
+ /* We need to flush widget base first to ensure correct ordering. */
+ UI_widgetbase_draw_cache_flush();
+
+#ifdef USE_UI_TOOLBAR_HACK
+ /* TODO(campbell): scale icons up for toolbar, we need a way to detect larger buttons and do this automatic. */
+ {
+ float scale = (float)ICON_DEFAULT_HEIGHT_TOOLBAR / (float)ICON_DEFAULT_HEIGHT;
+ y = (y + (h / 2)) - ((h * scale) / 2);
+ w *= scale;
+ h *= scale;
+ }
+#endif
+
+ /* This could re-generate often if rendered at different sizes in the one interface.
+ * TODO(campbell): support caching multiple sizes. */
+ ImBuf *ibuf = di->data.geom.image_cache;
+ if ((ibuf == NULL) ||
+ (ibuf->x != w) ||
+ (ibuf->y != h))
+ {
+ if (ibuf) {
+ IMB_freeImBuf(ibuf);
+ }
+ ibuf = BKE_icon_geom_rasterize(icon->obj, w, h);
+ di->data.geom.image_cache = ibuf;
+ }
+ glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ icon_draw_rect(x, y, w, h, aspect, w, h, ibuf->rect, alpha, rgb, desaturate);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ }
+ else if (di->type == ICON_TYPE_EVENT) {
+ const short event_type = di->data.input.event_type;
+ const short event_value = di->data.input.event_value;
+ icon_draw_rect_input(x, y, w, h, alpha, event_type, event_value);
+ }
else if (di->type == ICON_TYPE_TEXTURE) {
/* texture image use premul alpha for correct scaling */
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
icon_draw_texture(x, y, (float)w, (float)h, di->data.texture.x, di->data.texture.y,
di->data.texture.w, di->data.texture.h, alpha, rgb);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
}
+ else if (di->type == ICON_TYPE_MONO_TEXTURE) {
+ /* icon that matches text color, assumed to be white */
+ float text_color[4];
+ UI_GetThemeColor4fv(TH_TEXT, text_color);
+ if (rgb) {
+ mul_v3_v3(text_color, rgb);
+ }
+ text_color[3] *= alpha;
+
+ GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ icon_draw_texture(x, y, (float)w, (float)h, di->data.texture.x, di->data.texture.y,
+ di->data.texture.w, di->data.texture.h, text_color[3], text_color);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ }
+
else if (di->type == ICON_TYPE_BUFFER) {
/* it is a builtin icon */
iimg = di->data.buffer.image;
@@ -1119,9 +1467,9 @@ static void icon_draw_size(
#endif
if (!iimg->rect) return; /* something has gone wrong! */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, is_preview);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, desaturate);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
}
else if (di->type == ICON_TYPE_PREVIEW) {
PreviewImage *pi = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
@@ -1131,10 +1479,10 @@ static void icon_draw_size(
if (!pi->rect[size]) return; /* something has gone wrong! */
/* preview images use premul alpha ... */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- icon_draw_rect(x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], alpha, rgb, is_preview);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ icon_draw_rect(x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], alpha, rgb, desaturate);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
}
}
}
@@ -1162,7 +1510,7 @@ void UI_id_icon_render(const bContext *C, Scene *scene, ID *id, const bool big,
}
}
-static void ui_id_brush_render(const bContext *C, ID *id)
+static void ui_id_icon_render(const bContext *C, ID *id, bool use_jobs)
{
PreviewImage *pi = BKE_previewimg_id_ensure(id);
enum eIconSizes i;
@@ -1174,7 +1522,7 @@ static void ui_id_brush_render(const bContext *C, ID *id)
/* check if rect needs to be created; changed
* only set by dynamic icons */
if (((pi->flag[i] & PRV_CHANGED) || !pi->rect[i])) {
- icon_set_image(C, NULL, id, pi, i, true);
+ icon_set_image(C, NULL, id, pi, i, use_jobs);
pi->flag[i] &= ~PRV_CHANGED;
}
}
@@ -1187,19 +1535,25 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id)
if (br->flag & BRUSH_CUSTOM_ICON) {
BKE_icon_id_ensure(id);
- ui_id_brush_render(C, id);
+ ui_id_icon_render(C, id, true);
}
else {
+ WorkSpace *workspace = CTX_wm_workspace(C);
Object *ob = CTX_data_active_object(C);
- SpaceImage *sima;
const EnumPropertyItem *items = NULL;
int tool = PAINT_TOOL_DRAW, mode = 0;
+ ScrArea *sa = CTX_wm_area(C);
+ char space_type = sa->spacetype;
+ /* When in an unsupported space. */
+ if (!ELEM(space_type, SPACE_VIEW3D, SPACE_IMAGE)) {
+ space_type = workspace->tools_space_type;
+ }
/* XXX: this is not nice, should probably make brushes
* be strictly in one paint mode only to avoid
* checking various context stuff here */
- if (CTX_wm_view3d(C) && ob) {
+ if ((space_type == SPACE_VIEW3D) && ob) {
if (ob->mode & OB_MODE_SCULPT)
mode = OB_MODE_SCULPT;
else if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT))
@@ -1207,10 +1561,19 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id)
else if (ob->mode & OB_MODE_TEXTURE_PAINT)
mode = OB_MODE_TEXTURE_PAINT;
}
- else if ((sima = CTX_wm_space_image(C)) &&
- (sima->mode == SI_MODE_PAINT))
- {
- mode = OB_MODE_TEXTURE_PAINT;
+ else if (space_type == SPACE_IMAGE) {
+ int sima_mode;
+ if (sa->spacetype == space_type) {
+ SpaceImage *sima = sa->spacedata.first;
+ sima_mode = sima->mode;
+ }
+ else {
+ sima_mode = workspace->tools_mode;
+ }
+
+ if (sima_mode == SI_MODE_PAINT) {
+ mode = OB_MODE_TEXTURE_PAINT;
+ }
}
/* reset the icon */
@@ -1234,6 +1597,15 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id)
return id->icon_id;
}
+static int ui_id_screen_get_icon(const bContext *C, ID *id)
+{
+ BKE_icon_id_ensure(id);
+ /* Don't use jobs here, offscreen rendering doesn't like this and crashes. */
+ ui_id_icon_render(C, id, false);
+
+ return id->icon_id;
+}
+
int ui_id_icon_get(const bContext *C, ID *id, const bool big)
{
int iconid = 0;
@@ -1252,6 +1624,9 @@ int ui_id_icon_get(const bContext *C, ID *id, const bool big)
/* checks if not exists, or changed */
UI_id_icon_render(C, NULL, id, big, true);
break;
+ case ID_SCR:
+ iconid = ui_id_screen_get_icon(C, id);
+ break;
default:
break;
}
@@ -1277,7 +1652,7 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big
id = RNA_pointer_get(ptr, "texture").data;
}
else if (RNA_struct_is_a(ptr->type, &RNA_DynamicPaintSurface)) {
- DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data;
+ DynamicPaintSurface *surface = ptr->data;
if (surface->format == MOD_DPAINT_SURFACE_F_PTEX)
return ICON_TEXTURE_SHADED;
@@ -1286,6 +1661,18 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big
else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
return ICON_FILE_IMAGE;
}
+ else if (RNA_struct_is_a(ptr->type, &RNA_StudioLight)) {
+ StudioLight *sl = ptr->data;
+ switch (sl->flag & STUDIOLIGHT_FLAG_ORIENTATIONS) {
+ case STUDIOLIGHT_ORIENTATION_CAMERA:
+ return sl->icon_id_irradiance;
+ case STUDIOLIGHT_ORIENTATION_WORLD:
+ default:
+ return sl->icon_id_radiance;
+ case STUDIOLIGHT_ORIENTATION_VIEWNORMAL:
+ return sl->icon_id_matcap;
+ }
+ }
/* get icon from ID */
if (id) {
@@ -1319,7 +1706,7 @@ int UI_idcode_icon_get(const int idcode)
case ID_IM:
return ICON_IMAGE_DATA;
case ID_LA:
- return ICON_LAMP_DATA;
+ return ICON_LIGHT_DATA;
case ID_LS:
return ICON_LINE_DATA;
case ID_LT:
@@ -1344,6 +1731,8 @@ int UI_idcode_icon_get(const int idcode)
return ICON_COLOR; /* TODO! this would need its own icon! */
case ID_PC:
return ICON_CURVE_BEZCURVE; /* TODO! this would need its own icon! */
+ case ID_LP:
+ return ICON_LIGHTPROBE_CUBEMAP;
case ID_SCE:
return ICON_SCENE_DATA;
case ID_SPK:
@@ -1365,21 +1754,26 @@ int UI_idcode_icon_get(const int idcode)
static void icon_draw_at_size(
float x, float y, int icon_id, float aspect, float alpha,
- enum eIconSizes size, const bool nocreate)
+ enum eIconSizes size, const float desaturate)
{
int draw_size = get_draw_size(size);
- icon_draw_size(x, y, icon_id, aspect, alpha, NULL, size, draw_size, nocreate, false);
+ icon_draw_size(x, y, icon_id, aspect, alpha, NULL, size, draw_size, desaturate);
}
void UI_icon_draw_aspect(float x, float y, int icon_id, float aspect, float alpha)
{
- icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, 0);
+ icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, 0.0f);
}
void UI_icon_draw_aspect_color(float x, float y, int icon_id, float aspect, const float rgb[3])
{
int draw_size = get_draw_size(ICON_SIZE_ICON);
- icon_draw_size(x, y, icon_id, aspect, 1.0f, rgb, ICON_SIZE_ICON, draw_size, false, false);
+ icon_draw_size(x, y, icon_id, aspect, 1.0f, rgb, ICON_SIZE_ICON, draw_size, false);
+}
+
+void UI_icon_draw_desaturate(float x, float y, int icon_id, float aspect, float alpha, float desaturate)
+{
+ icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, desaturate);
}
/* draws icon with dpi scale factor */
@@ -1388,22 +1782,27 @@ void UI_icon_draw(float x, float y, int icon_id)
UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, 1.0f);
}
+void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha)
+{
+ UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, alpha);
+}
+
void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha)
{
- icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, ICON_SIZE_ICON, size, true, false);
+ icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, ICON_SIZE_ICON, size, false);
}
void UI_icon_draw_preview(float x, float y, int icon_id)
{
- icon_draw_at_size(x, y, icon_id, 1.0f, 1.0f, ICON_SIZE_PREVIEW, 0);
+ icon_draw_at_size(x, y, icon_id, 1.0f, 1.0f, ICON_SIZE_PREVIEW, false);
}
void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect)
{
- icon_draw_at_size(x, y, icon_id, aspect, 1.0f, ICON_SIZE_PREVIEW, 0);
+ icon_draw_at_size(x, y, icon_id, aspect, 1.0f, ICON_SIZE_PREVIEW, false);
}
void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, float alpha, int size)
{
- icon_draw_size(x, y, icon_id, aspect, alpha, NULL, ICON_SIZE_PREVIEW, size, false, true);
+ icon_draw_size(x, y, icon_id, aspect, alpha, NULL, ICON_SIZE_PREVIEW, size, false);
}
diff --git a/source/blender/editors/interface/interface_icons_event.c b/source/blender/editors/interface/interface_icons_event.c
new file mode 100644
index 00000000000..dc444b98b2c
--- /dev/null
+++ b/source/blender/editors/interface/interface_icons_event.c
@@ -0,0 +1,295 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/interface/interface_icons_event.c
+ * \ingroup edinterface
+ *
+ * A special set of icons to represent input devices,
+ * this is a mix of text (via fonts) and a handful of custom glyphs for special keys.
+ *
+ * Event codes are used as identifiers.
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "GPU_draw.h"
+#include "GPU_matrix.h"
+#include "GPU_batch.h"
+#include "GPU_immediate.h"
+#include "GPU_state.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_fileops_types.h"
+#include "BLI_math_vector.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_dynamicpaint_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_workspace_types.h"
+
+#include "RNA_access.h"
+#include "RNA_enum_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_icons.h"
+#include "BKE_appdir.h"
+#include "BKE_studiolight.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_thumbs.h"
+
+#include "BIF_glutil.h"
+#include "BLF_api.h"
+
+#include "DEG_depsgraph.h"
+
+#include "DRW_engine.h"
+
+#include "ED_datafiles.h"
+#include "ED_keyframes_draw.h"
+#include "ED_render.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "interface_intern.h"
+
+static void icon_draw_rect_input_small_text_ex(
+ const rctf *rect, const float color[4], const float margin[2], const char *str,
+ int font_size)
+{
+ BLF_batch_draw_flush();
+ const int font_id = BLF_default();
+ BLF_color4fv(font_id, color);
+ BLF_size(font_id, font_size * U.pixelsize, U.dpi);
+ BLF_position(font_id, rect->xmin + margin[0] * 2, rect->ymin + margin[1] * 5, 0.0f);
+ BLF_draw(font_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_batch_draw_flush();
+}
+
+static void icon_draw_rect_input_small_text(
+ const rctf *rect, const float color[4], const float margin[2], const char *str)
+{
+ icon_draw_rect_input_small_text_ex(rect, color, margin, str, 8);
+}
+
+static void icon_draw_rect_input_default_text(
+ const rctf *rect,
+ const float color[4], const float margin[2], const char *str)
+{
+ BLF_batch_draw_flush();
+ const int font_id = BLF_default();
+ BLF_color4fv(font_id, color);
+ BLF_position(font_id, (int)(rect->xmin + margin[0] * 5), (int)(rect->ymin + margin[1] * 5), 0.0f);
+ BLF_draw(font_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_batch_draw_flush();
+}
+
+static void icon_draw_rect_input_mono_text(
+ const rctf *rect,
+ const float color[4], const float margin[2], const char *str)
+{
+ BLF_batch_draw_flush();
+ const int font_id = blf_mono_font;
+ BLF_color4fv(font_id, color);
+ BLF_size(font_id, 20 * U.pixelsize, U.dpi);
+ BLF_position(font_id, (int)(rect->xmin + margin[0] * 5), (int)(rect->ymin + margin[1] * 5), 0.0f);
+ BLF_draw(font_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_batch_draw_flush();
+}
+
+static void icon_draw_rect_input_line_prim(
+ const rctf *rect,
+ const float color[4],
+ const int prim,
+ const char lines[][2], int lines_len)
+{
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ BLI_assert(ELEM(prim, GWN_PRIM_LINE_LOOP, GWN_PRIM_LINE_STRIP));
+ const uint pos_id = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
+ immBegin(prim, lines_len);
+ float w_inv = BLI_rctf_size_x(rect) / 255.0f;
+ float h_inv = BLI_rctf_size_y(rect) / 255.0f;
+ for (int i = 0; i < lines_len; i++) {
+ immVertex2f(
+ pos_id,
+ round_fl_to_int(rect->xmin + ((float)lines[i][0] * w_inv)),
+ round_fl_to_int(rect->ymin + ((float)lines[i][1] * h_inv))
+ );
+ }
+ immEnd();
+ immUnbindProgram();
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+}
+
+void icon_draw_rect_input(
+ float x, float y, int w, int h, float UNUSED(alpha),
+ short event_type, short UNUSED(event_value))
+{
+ float color[4];
+ const float margin[2] = {w / 20.0f, h / 20.0f};
+ UI_GetThemeColor4fv(TH_TEXT, color);
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_aa(
+ false,
+ (int)x,
+ (int)y,
+ (int)(x + w),
+ (int)(y + h), 4.0f, color
+ );
+
+ const rctf rect = {
+ .xmin = x,
+ .ymin = y,
+ .xmax = x + w,
+ .ymax = y + h,
+ };
+
+ const bool simple_text = false;
+
+ if ((event_type >= AKEY) || (ZKEY <= event_type)) {
+ char str[2] = {'A' + (event_type - AKEY), '\0'};
+ icon_draw_rect_input_default_text(&rect, color, margin, str);
+ }
+ if ((event_type >= F1KEY) || (F12KEY <= event_type)) {
+ char str[3] = {'F', '1' + (event_type - F1KEY), '\0'};
+ icon_draw_rect_input_default_text(&rect, color, margin, str);
+ }
+ else if (event_type == LEFTSHIFTKEY) {
+ if (simple_text) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Shift");
+ }
+ else {
+ rctf rect_ofs = rect;
+ BLI_rctf_translate(&rect_ofs, (w / -14.0f), (w / -14.0f));
+ icon_draw_rect_input_mono_text(&rect_ofs, color, margin, (const char[]){0xe2, 0x87, 0xa7, 0x0});
+ }
+ }
+ else if (event_type == LEFTCTRLKEY) {
+ if (simple_text) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Ctrl");
+ }
+ else {
+ rctf rect_ofs = rect;
+ BLI_rctf_translate(&rect_ofs, (w / -16.0f), 0.0f);
+ icon_draw_rect_input_default_text(&rect_ofs, color, margin, "^");
+ }
+ }
+ else if (event_type == LEFTALTKEY) {
+ if (simple_text) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Alt");
+ }
+ else {
+ rctf rect_ofs = rect;
+ BLI_rctf_translate(&rect_ofs, (w / -8.0f), 0.0f);
+ icon_draw_rect_input_default_text(&rect_ofs, color, margin, (const char[]){0xe2, 0x8c, 0xa5, 0x0});
+ }
+ }
+ else if (event_type == OSKEY) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "OS");
+ }
+ else if (event_type == DELKEY) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Del");
+ }
+ else if (event_type == TABKEY) {
+ if (simple_text) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Tab");
+ }
+ else {
+ rctf rect_ofs = rect;
+ BLI_rctf_translate(&rect_ofs, (w / -12.0f), (w / -12.0f));
+ icon_draw_rect_input_mono_text(&rect_ofs, color, margin, (const char[]){0xe2, 0x86, 0xb9, 0x0});
+ }
+ }
+ else if (event_type == HOMEKEY) {
+ if (simple_text) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Home");
+ }
+ else {
+ rctf rect_ofs = rect;
+ BLI_rctf_translate(&rect_ofs, (w / -12.0f), (w / -12.0f));
+ icon_draw_rect_input_mono_text(&rect_ofs, color, margin, (const char[]){0xe2, 0x87, 0xa4, 0x0});
+ }
+ }
+ else if (event_type == ENDKEY) {
+ if (simple_text) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "End");
+ }
+ else {
+ rctf rect_ofs = rect;
+ BLI_rctf_translate(&rect_ofs, (w / -12.0f), (w / -12.0f));
+ icon_draw_rect_input_mono_text(&rect_ofs, color, margin, (const char[]){0xe2, 0x87, 0xa5, 0x0});
+ }
+ }
+ else if (event_type == RETKEY) {
+ if (simple_text) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Ret");
+ }
+ else {
+ rctf rect_ofs = rect;
+ BLI_rctf_translate(&rect_ofs, (w / -8.0f), (w / -6.0f));
+ icon_draw_rect_input_mono_text(&rect_ofs, color, margin, (const char[]){0xe2, 0x8f, 0x8e, 0x0});
+ }
+ }
+ else if (event_type == ESCKEY) {
+ icon_draw_rect_input_small_text(&rect, color, margin, "Esc");
+ }
+ else if (event_type == PAGEUPKEY) {
+ icon_draw_rect_input_small_text_ex(&rect, color, margin, (const char[]){'P', 0xe2, 0x86, 0x91, 0x0}, 10);
+ }
+ else if (event_type == PAGEDOWNKEY) {
+ icon_draw_rect_input_small_text_ex(&rect, color, margin, (const char[]){'P', 0xe2, 0x86, 0x93, 0x0}, 10);
+ }
+ else if (event_type == LEFTARROWKEY) {
+ icon_draw_rect_input_default_text(&rect, color, margin, (const char[]){0xe2, 0x86, 0x90, 0x0});
+ }
+ else if (event_type == UPARROWKEY) {
+ icon_draw_rect_input_default_text(&rect, color, margin, (const char[]){0xe2, 0x86, 0x91, 0x0});
+ }
+ else if (event_type == RIGHTARROWKEY) {
+ icon_draw_rect_input_default_text(&rect, color, margin, (const char[]){0xe2, 0x86, 0x92, 0x0});
+ }
+ else if (event_type == DOWNARROWKEY) {
+ icon_draw_rect_input_default_text(&rect, color, margin, (const char[]){0xe2, 0x86, 0x93, 0x0});
+ }
+ else if (event_type == SPACEKEY) {
+ const uchar lines[] = {60, 118, 60, 60, 195, 60, 195, 118};
+ icon_draw_rect_input_line_prim(
+ &rect, color, GWN_PRIM_LINE_STRIP,
+ (const void *)lines, ARRAY_SIZE(lines) / 2);
+ }
+}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index cc86530871d..ffc389c6dfd 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -72,6 +72,8 @@ typedef enum {
UI_WTYPE_NUMBER,
UI_WTYPE_SLIDER,
UI_WTYPE_EXEC,
+ UI_WTYPE_TOOLBAR_ITEM,
+ UI_WTYPE_TAB,
UI_WTYPE_TOOLTIP,
/* strings */
@@ -103,6 +105,9 @@ typedef enum {
UI_WTYPE_PROGRESSBAR,
} uiWidgetTypeEnum;
+#define UI_MENU_WIDTH_MIN (UI_UNIT_Y * 9)
+#define UI_MENU_SUBMENU_PADDING (6 * UI_DPI_FAC) /* some extra padding added to menus containing submenu icons */
+
/* menu scrolling */
#define UI_MENU_SCROLL_ARROW 12
#define UI_MENU_SCROLL_MOUSE (UI_MENU_SCROLL_ARROW + 2)
@@ -112,6 +117,9 @@ typedef enum {
#define UI_PANEL_MINX 100
#define UI_PANEL_MINY 70
+/* popover width (multiplied by 'U.widget_unit') */
+#define UI_POPOVER_WIDTH_UNITS 10
+
/* uiBut->flag */
enum {
UI_SELECT = (1 << 0), /* use when the button is pressed */
@@ -187,23 +195,6 @@ enum {
/* max amount of items a radial menu (pie menu) can contain */
#define PIE_MAX_ITEMS 8
-typedef struct uiLinkLine { /* only for draw/edit */
- struct uiLinkLine *next, *prev;
- struct uiBut *from, *to;
- short flag, deactive;
-} uiLinkLine;
-
-typedef struct {
- void **poin; /* pointer to original pointer */
- void ***ppoin; /* pointer to original pointer-array */
- short *totlink; /* if pointer-array, here is the total */
-
- short maxlink, pad;
- short fromcode, tocode;
-
- ListBase lines;
-} uiLink;
-
struct uiBut {
struct uiBut *next, *prev;
int flag, drawflag;
@@ -258,6 +249,7 @@ struct uiBut {
uiButSearchCreateFunc search_create_func;
uiButSearchFunc search_func;
+ bool free_search_arg;
void *search_arg;
uiButHandleRenameFunc rename_func;
@@ -268,9 +260,6 @@ struct uiBut {
uiButHandleHoldFunc hold_func;
void *hold_argN;
- uiLink *link;
- short linkto[2]; /* region relative coords */
-
const char *tip;
uiButToolTipFunc tip_func;
void *tip_argN;
@@ -281,7 +270,7 @@ struct uiBut {
BIFIconID icon;
char dt; /* drawtype: UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied from the block */
signed char pie_dir; /* direction in a pie menu, used for collision detection (RadialDirection) */
- char changed; /* could be made into a single flag */
+ bool changed; /* could be made into a single flag */
unsigned char unit_type; /* so buttons can support unit systems which are not RNA */
short modifier_key;
short iconadd;
@@ -331,6 +320,11 @@ struct uiBut {
uiBlock *block;
};
+typedef struct uiButTab {
+ uiBut but;
+ struct wmOperatorType *unlink_ot;
+} uiButTab;
+
typedef struct ColorPicker {
struct ColorPicker *next, *prev;
float color_data[3]; /* colr data may be HSV or HSL for now */
@@ -356,6 +350,13 @@ struct PieMenuData {
float alphafac;
};
+/* uiBlock.content_hints */
+enum eBlockContentHints {
+ /* In a menu block, if there is a single sub-menu button, we add some
+ * padding to the right to put nicely aligned triangle icons there. */
+ BLOCK_CONTAINS_SUBMENU_BUT = (1 << 0),
+};
+
struct uiBlock {
uiBlock *next, *prev;
@@ -402,11 +403,15 @@ struct uiBlock {
int flag;
short alignnr;
+ /* Hints about the buttons of this block. Used to avoid iterating over
+ * buttons to find out if some criteria is met by any. Instead, check this
+ * criteria when adding the button and set a flag here if it's met. */
+ short content_hints; /* eBlockContentHints */
char direction;
char dt; /* drawtype: UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied to buttons */
bool auto_open;
- char _pad[7];
+ char _pad[5];
double auto_open_last;
const char *lockstr;
@@ -449,8 +454,6 @@ typedef struct uiSafetyRct {
/* interface.c */
-extern void ui_linkline_remove(uiLinkLine *line, uiBut *but);
-
void ui_fontscale(short *points, float aspect);
extern void ui_block_to_window_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y);
@@ -505,9 +508,9 @@ extern bool ui_but_supports_cycling(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern int ui_but_is_pushed_ex(uiBut *but, double *value) ATTR_WARN_UNUSED_RESULT;
extern int ui_but_is_pushed(uiBut *but) ATTR_WARN_UNUSED_RESULT;
+void ui_but_override_flag(uiBut *but);
extern void ui_block_bounds_calc(uiBlock *block);
-extern void ui_block_translate(uiBlock *block, int x, int y);
extern struct ColorManagedDisplay *ui_block_cm_display_get(uiBlock *block);
void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3]);
@@ -524,16 +527,19 @@ struct uiKeyNavLock {
};
typedef uiBlock * (*uiBlockHandleCreateFunc)(struct bContext *C, struct uiPopupBlockHandle *handle, void *arg1);
+typedef void (*uiBlockHandleFreeFunc)(struct uiPopupBlockHandle *handle, void *arg1);
struct uiPopupBlockCreate {
- uiBlockCreateFunc create_func;
+ uiBlockCreateFunc create_func;
uiBlockHandleCreateFunc handle_create_func;
+ uiBlockHandleFreeFunc free_func;
void *arg;
int event_xy[2];
/* when popup is initialized from a button */
ARegion *butregion;
+ uiBut *but;
};
struct uiPopupBlockHandle {
@@ -554,8 +560,10 @@ 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;
+ float scrolloffset;
struct uiKeyNavLock keynav_state;
@@ -575,6 +583,15 @@ struct uiPopupBlockHandle {
/* menu direction */
int direction;
+ /* 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;
int grab_xy_prev[2];
@@ -627,13 +644,25 @@ uiPopupBlockHandle *ui_popup_menu_create(
struct bContext *C, struct ARegion *butregion, uiBut *but,
uiMenuCreateFunc create_func, void *arg);
+/* interface_region_popover.c */
+uiBlock *ui_popover_block_refresh(
+ struct bContext *C, uiPopupBlockHandle *handle,
+ ARegion *butregion, uiBut *but);
+uiPopupBlockHandle *ui_popover_block_create(
+ struct bContext *C, struct ARegion *butregion, uiBut *but,
+ uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func,
+ void *arg);
+uiPopupBlockHandle *ui_popover_panel_create(
+ struct bContext *C, struct ARegion *butregion, uiBut *but,
+ uiMenuCreateFunc create_func, void *arg);
+
/* interface_region_menu_pie.c */
void ui_pie_menu_level_create(
uiBlock *block, struct wmOperatorType *ot, const char *propname, IDProperty *properties,
const EnumPropertyItem *items, int totitem, int context, int flag);
/* interface_region_popup.c */
-void ui_popup_translate(struct bContext *C, struct ARegion *ar, const int mdiff[2]);
+void ui_popup_translate(struct ARegion *ar, const int mdiff[2]);
void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle);
void ui_popup_block_scrolltest(struct uiBlock *block);
@@ -651,6 +680,8 @@ extern void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, floa
void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha);
+
+void ui_draw_but_TAB_outline(const rcti *rect, float rad, unsigned char highlight[3], unsigned char highlight_fade[3]);
void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
@@ -690,20 +721,55 @@ struct wmIMEData *ui_but_ime_data_get(uiBut *but);
#endif
/* interface_widgets.c */
-void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3);
-void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha);
+
+/* Widget shader parameters, must match the shader layout. */
+typedef struct uiWidgetBaseParameters {
+ rctf recti, rect;
+ float radi, rad;
+ float facxi, facyi;
+ float round_corners[4];
+ float color_inner1[4], color_inner2[4];
+ float color_outline[4], color_emboss[4];
+ float color_tria[4];
+ float tria1_center[2], tria2_center[2];
+ float tria1_size, tria2_size;
+ float shade_dir;
+ /* We pack alpha check and discard factor in alpha_discard.
+ * If the value is negative then we do alpha check.
+ * The absolute value itself is the discard factor.
+ * Initialize value to 1.0.f if you don't want discard */
+ float alpha_discard;
+} uiWidgetBaseParameters;
+
+enum {
+ ROUNDBOX_TRIA_NONE = 0,
+ ROUNDBOX_TRIA_ARROWS,
+ ROUNDBOX_TRIA_SCROLL,
+ ROUNDBOX_TRIA_MENU,
+ ROUNDBOX_TRIA_CHECK,
+ ROUNDBOX_TRIA_HOLD_ACTION_ARROW,
+
+ ROUNDBOX_TRIA_MAX, /* don't use */
+};
+
+struct Gwn_Batch *ui_batch_roundbox_get(bool filled, bool antialiased);
+struct Gwn_Batch *ui_batch_roundbox_widget_get(int tria);
+struct Gwn_Batch *ui_batch_roundbox_shadow_get(void);
+
+void ui_draw_anti_tria_rect(const rctf *rect, char dir, const float color[4]);
void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect);
+void ui_draw_popover_back(ARegion *ar, struct uiStyle *style, uiBlock *block, rcti *rect);
void ui_draw_pie_center(uiBlock *block);
struct uiWidgetColors *ui_tooltip_get_theme(void);
+
+void ui_draw_widget_back_color(
+ uiWidgetTypeEnum type, bool use_shadow, const rcti *rect,
+ const float color[4]);
+void ui_draw_widget_back(
+ uiWidgetTypeEnum type, bool use_shadow, const rcti *rect);
void ui_draw_tooltip_background(struct uiStyle *UNUSED(style), uiBlock *block, rcti *rect);
-void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect);
-bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol);
-void ui_draw_link_bezier(const rcti *rect);
extern void ui_draw_but(const struct bContext *C, ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect);
-/* theme color init */
-struct ThemeUI;
-void ui_widget_color_init(struct ThemeUI *tui);
void ui_draw_menu_item(struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep);
void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state);
@@ -713,6 +779,9 @@ void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, const char *na
/* margin at top of screen for popups */
#define UI_POPUP_MENU_TOP (int)(8 * UI_DPI_FAC)
+#define UI_PIXEL_AA_JITTER 8
+const float ui_pixel_jitter[UI_PIXEL_AA_JITTER][2];
+
/* interface_style.c */
void uiStyleInit(void);
@@ -720,6 +789,11 @@ void uiStyleInit(void);
void ui_icon_ensure_deferred(const struct bContext *C, const int icon_id, const bool big);
int ui_id_icon_get(const struct bContext *C, struct ID *id, const bool big);
+/* interface_icons_event.c */
+void icon_draw_rect_input(
+ float x, float y, int w, int h, float alpha,
+ short event_type, short event_value);
+
/* resources.c */
void init_userdef_do_versions(struct Main *bmain);
void ui_theme_init_default(void);
@@ -731,10 +805,12 @@ void ui_resources_free(void);
void ui_layout_add_but(uiLayout *layout, uiBut *but);
void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop);
void ui_layout_list_set_labels_active(uiLayout *layout);
+/* menu callback */
+void ui_item_paneltype_func(struct bContext *C, struct uiLayout *layout, void *arg_pt);
/* interface_align.c */
bool ui_but_can_align(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
-void ui_block_align_calc(uiBlock *block);
+void ui_block_align_calc(uiBlock *block, const ARegion *region);
/* interface_anim.c */
void ui_but_anim_flag(uiBut *but, float cfra);
@@ -745,10 +821,14 @@ bool ui_but_anim_expression_set(uiBut *but, const char *str);
bool ui_but_anim_expression_create(uiBut *but, const char *str);
void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, float cfra);
+void ui_but_anim_decorate_cb(struct bContext *C, void *arg_but, void *arg_dummy);
+void ui_but_anim_decorate_update_from_flag(uiBut *but);
+
/* interface_query.c */
bool ui_but_is_editable(const uiBut *but);
bool ui_but_is_editable_as_text(const uiBut *but);
bool ui_but_is_toggle(const uiBut *but);
+bool ui_but_is_popover_once_compat(const uiBut *but);
extern bool ui_block_is_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
extern bool ui_block_is_pie_menu(const uiBlock *block) ATTR_WARN_UNUSED_RESULT;
@@ -777,4 +857,20 @@ void UI_OT_eyedropper_depth(struct wmOperatorType *ot);
/* interface_eyedropper_driver.c */
void UI_OT_eyedropper_driver(struct wmOperatorType *ot);
+/* interface_util.c */
+
+/**
+ * For use with #ui_rna_collection_search_cb.
+ */
+typedef struct uiRNACollectionSearch {
+ PointerRNA target_ptr;
+ PropertyRNA *target_prop;
+
+ PointerRNA search_ptr;
+ PropertyRNA *search_prop;
+
+ bool *but_changed; /* pointer to uiBut.changed */
+} uiRNACollectionSearch;
+void ui_rna_collection_search_cb(const struct bContext *C, void *arg, const char *str, uiSearchItems *items);
+
#endif /* __INTERFACE_INTERN_H__ */
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index e830d70e308..16016a799ef 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -37,6 +37,7 @@
#include "DNA_armature_types.h"
#include "DNA_userdef_types.h"
+#include "BLI_alloca.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_rect.h"
@@ -49,6 +50,7 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_screen.h"
+#include "BKE_animsys.h"
#include "RNA_access.h"
@@ -62,6 +64,13 @@
#include "interface_intern.h"
+/* Show an icon button after each RNA button to use to quickly set keyframes,
+ * this is a way to display animation/driven/override status, see T54951. */
+#define UI_PROP_DECORATE
+/* Alternate draw mode where some buttons can use single icon width,
+ * giving more room for the text at the expense of nicely aligned text. */
+#define UI_PROP_SEP_ICON_WIDTH_EXCEPTION
+
/************************ Structs and Defines *************************/
#define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement) \
@@ -71,6 +80,7 @@
return_statement; \
} (void)0 \
+#define UI_ITEM_PROP_SEP_DIVIDE 0.5f
/* uiLayoutRoot */
@@ -100,6 +110,7 @@ typedef enum uiItemType {
ITEM_LAYOUT_COLUMN,
ITEM_LAYOUT_COLUMN_FLOW,
ITEM_LAYOUT_ROW_FLOW,
+ ITEM_LAYOUT_GRID_FLOW,
ITEM_LAYOUT_BOX,
ITEM_LAYOUT_ABSOLUTE,
ITEM_LAYOUT_SPLIT,
@@ -128,6 +139,10 @@ enum {
UI_ITEM_MIN = 1 << 1,
UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */
+ UI_ITEM_PROP_SEP = 1 << 3,
+ /* Show an icon button next to each property (to set keyframes, show status).
+ * Enabled by default, depends on 'UI_ITEM_PROP_SEP'. */
+ UI_ITEM_PROP_DECORATE = 1 << 4,
};
typedef struct uiButtonItem {
@@ -150,7 +165,9 @@ struct uiLayout {
bool enabled;
bool redalert;
bool keepaspect;
+ bool variable_size; /* For layouts inside gridflow, they and their items shall never have a fixed maximal size. */
char alignment;
+ char emboss;
};
typedef struct uiLayoutItemFlow {
@@ -159,6 +176,22 @@ typedef struct uiLayoutItemFlow {
int totcol;
} uiLayoutItemFlow;
+typedef struct uiLayoutItemGridFlow {
+ uiLayout litem;
+
+ /* Extra parameters */
+ bool row_major; /* Fill first row first, instead of filling first column first. */
+ bool even_columns; /* Same width for all columns. */
+ bool even_rows; /* Same height for all rows. */
+ /* If positive, absolute fixed number of columns.
+ * If 0, fully automatic (based on available width).
+ * If negative, automatic but only generates number of columns/rows multiple of given (absolute) value. */
+ int columns_len;
+
+ /* Pure internal runtime storage. */
+ int tot_items, tot_columns, tot_rows;
+} uiLayoutItemGridFlow;
+
typedef struct uiLayoutItemBx {
uiLayout litem;
uiBut *roundbox;
@@ -234,29 +267,37 @@ static int ui_layout_vary_direction(uiLayout *layout)
UI_ITEM_VARY_X : UI_ITEM_VARY_Y);
}
+static bool ui_layout_variable_size(uiLayout *layout)
+{
+ /* Note that this code is probably a bit flacky, we'd probably want to know whether it's variable in X and/or Y,
+ * etc. But for now it mimics previous one, with addition of variable flag set for children of gridflow layouts. */
+ return ui_layout_vary_direction(layout) == UI_ITEM_VARY_X || layout->variable_size;
+}
+
/* estimated size of text + icon */
static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, bool compact)
{
bool variable;
+ const int unit_x = UI_UNIT_X * (layout->scale[0] ? layout->scale[0] : 1.0f);
if (icon && !name[0])
- return UI_UNIT_X; /* icon only */
+ return unit_x; /* icon only */
- variable = (ui_layout_vary_direction(layout) == UI_ITEM_VARY_X);
+ variable = ui_layout_variable_size(layout);
if (variable) {
if (layout->alignment != UI_LAYOUT_ALIGN_EXPAND) {
layout->item.flag |= UI_ITEM_MIN;
}
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- /* it may seem odd that the icon only adds (UI_UNIT_X / 4)
+ /* it may seem odd that the icon only adds (unit_x / 4)
* but taking margins into account its fine */
return (UI_fontstyle_string_width(fstyle, name) +
- (UI_UNIT_X * ((compact ? 1.25f : 1.50f) +
- (icon ? 0.25f : 0.0f))));
+ (unit_x * ((compact ? 1.25f : 1.50f) +
+ (icon ? 0.25f : 0.0f))));
}
else {
- return UI_UNIT_X * 10;
+ return unit_x * 10;
}
}
@@ -343,6 +384,7 @@ static int ui_layout_local_dir(uiLayout *layout)
return UI_LAYOUT_HORIZONTAL;
case ITEM_LAYOUT_COLUMN:
case ITEM_LAYOUT_COLUMN_FLOW:
+ case ITEM_LAYOUT_GRID_FLOW:
case ITEM_LAYOUT_SPLIT:
case ITEM_LAYOUT_ABSOLUTE:
case ITEM_LAYOUT_BOX:
@@ -392,7 +434,7 @@ static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index)
static void ui_item_array(
uiLayout *layout, uiBlock *block, const char *name, int icon,
PointerRNA *ptr, PropertyRNA *prop, int len, int x, int y, int w, int UNUSED(h),
- bool expand, bool slider, bool toggle, bool icon_only)
+ bool expand, bool slider, bool toggle, bool icon_only, bool compact, bool show_text)
{
uiStyle *style = layout->root->style;
uiBut *but;
@@ -409,8 +451,9 @@ static void ui_item_array(
UI_block_layout_set_current(block, sub);
/* create label */
- if (name[0])
+ if (name[0] && show_text) {
uiDefBut(block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ }
/* create buttons */
if (type == PROP_BOOLEAN && ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER)) {
@@ -528,7 +571,7 @@ static void ui_item_array(
/* layout for known array subtypes */
char str[3] = {'\0'};
- if (!icon_only) {
+ if (!icon_only && show_text) {
if (type != PROP_BOOLEAN) {
str[1] = ':';
}
@@ -540,10 +583,22 @@ static void ui_item_array(
RNA_property_boolean_get_array(ptr, prop, boolarr);
}
+ const char *str_buf = show_text ? str: "";
for (a = 0; a < len; a++) {
- if (!icon_only) str[0] = RNA_property_array_item_char(prop, a);
- if (boolarr) icon = boolarr[a] ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
- but = uiDefAutoButR(block, ptr, prop, a, str, icon, 0, 0, w, UI_UNIT_Y);
+ int width_item;
+
+ if (!icon_only && show_text) {
+ str[0] = RNA_property_array_item_char(prop, a);
+ }
+ if (boolarr) {
+ icon = boolarr[a] ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+ }
+
+ width_item = (
+ (compact && type == PROP_BOOLEAN) ?
+ min_ii(w, ui_text_icon_width(layout, str_buf, icon, false)) : w);
+
+ but = uiDefAutoButR(block, ptr, prop, a, str_buf, icon, 0, 0, width_item, UI_UNIT_Y);
if (slider && but->type == UI_BTYPE_NUM)
but->type = UI_BTYPE_NUM_SLIDER;
if (toggle && but->type == UI_BTYPE_CHECKBOX)
@@ -626,8 +681,14 @@ static void ui_item_enum_expand(
for (item = item_array; item->identifier; item++) {
if (!item->identifier[0]) {
- if (radial && layout_radial) {
- uiItemS(layout_radial);
+ const EnumPropertyItem *next_item = item + 1;
+ if (next_item->identifier) {
+ if (radial && layout_radial) {
+ uiItemS(layout_radial);
+ }
+ else {
+ uiItemS(block->curlayout);
+ }
}
continue;
}
@@ -669,27 +730,49 @@ static void ui_keymap_but_cb(bContext *UNUSED(C), void *but_v, void *UNUSED(key_
RNA_boolean_set(&but->rnapoin, "oskey", (but->modifier_key & KM_OSKEY) != 0);
}
-/* create label + button for RNA property */
-static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w, int h, int flag)
+/**
+ * Create label + button for RNA property
+ *
+ * \param w_hint: For varying width layout, this becomes the label width.
+ * Otherwise it's used to fit both items into it.
+ **/
+static uiBut *ui_item_with_label(
+ uiLayout *layout, uiBlock *block, const char *name, int icon,
+ PointerRNA *ptr, PropertyRNA *prop, int index,
+ int x, int y, int w_hint, int h, int flag)
{
uiLayout *sub;
uiBut *but = NULL;
PropertyType type;
PropertySubType subtype;
- int labelw;
+ int prop_but_width = w_hint;
+ const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
sub = uiLayoutRow(layout, layout->align);
UI_block_layout_set_current(block, sub);
if (name[0]) {
- /* XXX UI_fontstyle_string_width is not accurate */
-#if 0
- labelw = UI_fontstyle_string_width(fstyle, name);
- CLAMP(labelw, w / 4, 3 * w / 4);
-#endif
- labelw = w / 3;
- uiDefBut(block, UI_BTYPE_LABEL, 0, name, x, y, labelw, h, NULL, 0.0, 0.0, 0, 0, "");
- w = w - labelw;
+ int w_label;
+
+ if (use_prop_sep) {
+ w_label = (int)((w_hint * 2) * UI_ITEM_PROP_SEP_DIVIDE);
+ }
+ else {
+ if (ui_layout_variable_size(layout)) {
+ /* w_hint is width for label in this case. Use a default width for property button(s) */
+ prop_but_width = UI_UNIT_X * 5;
+ w_label = w_hint;
+ }
+ else {
+ w_label = w_hint / 3;
+ }
+ }
+
+ uiBut *but_label = uiDefBut(block, UI_BTYPE_LABEL, 0, name, x, y, w_label, h, NULL, 0.0, 0.0, 0, 0, "");
+ if (use_prop_sep) {
+ but_label->drawflag |= UI_BUT_TEXT_RIGHT;
+ but_label->drawflag &= ~UI_BUT_TEXT_LEFT;
+ }
}
type = RNA_property_type(prop);
@@ -697,7 +780,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n
if (subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
UI_block_layout_set_current(block, uiLayoutRow(sub, true));
- but = uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w - UI_UNIT_X, h);
+ but = uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, prop_but_width - UI_UNIT_X, h);
/* BUTTONS_OT_file_browse calls UI_context_active_but_prop_get_filebrowser */
uiDefIconButO(
@@ -705,7 +788,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n
WM_OP_INVOKE_DEFAULT, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL);
}
else if (flag & UI_ITEM_R_EVENT) {
- but = uiDefButR_prop(block, UI_BTYPE_KEY_EVENT, 0, name, x, y, w, h, ptr, prop, index, 0, 0, -1, -1, NULL);
+ but = uiDefButR_prop(block, UI_BTYPE_KEY_EVENT, 0, name, x, y, prop_but_width, h, ptr, prop, index, 0, 0, -1, -1, NULL);
}
else if (flag & UI_ITEM_R_FULL_EVENT) {
if (RNA_struct_is_a(ptr->type, &RNA_KeyMapItem)) {
@@ -713,14 +796,18 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n
WM_keymap_item_to_string(ptr->data, false, buf, sizeof(buf));
- but = uiDefButR_prop(block, UI_BTYPE_HOTKEY_EVENT, 0, buf, x, y, w, h, ptr, prop, 0, 0, 0, -1, -1, NULL);
+ but = uiDefButR_prop(block, UI_BTYPE_HOTKEY_EVENT, 0, buf, x, y, prop_but_width, h, ptr, prop, 0, 0, 0, -1, -1, NULL);
UI_but_func_set(but, ui_keymap_but_cb, but, NULL);
if (flag & UI_ITEM_R_IMMEDIATE)
UI_but_flag_enable(but, UI_BUT_IMMEDIATE);
}
}
- else
- but = uiDefAutoButR(block, ptr, prop, index, (type == PROP_ENUM && !(flag & UI_ITEM_R_ICON_ONLY)) ? NULL : "", icon, x, y, w, h);
+ else {
+ const char *str = (type == PROP_ENUM && !(flag & UI_ITEM_R_ICON_ONLY)) ? NULL : "";
+ but = uiDefAutoButR(
+ block, ptr, prop, index, str, icon,
+ x, y, prop_but_width, h);
+ }
UI_block_layout_set_current(block, layout);
return but;
@@ -821,8 +908,10 @@ static uiBut *uiItemFullO_ptr_ex(
w = ui_text_icon_width(layout, name, icon, 0);
- if (flag & UI_ITEM_R_NO_BG)
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ int prev_emboss = layout->emboss;
+ if (flag & UI_ITEM_R_NO_BG) {
+ layout->emboss = UI_EMBOSS_NONE;
+ }
/* create the button */
if (icon) {
@@ -843,8 +932,9 @@ static uiBut *uiItemFullO_ptr_ex(
if ((layout->root->type == UI_LAYOUT_TOOLBAR) && !icon)
but->drawflag |= UI_BUT_TEXT_LEFT;
- if (flag & UI_ITEM_R_NO_BG)
- UI_block_emboss_set(block, UI_EMBOSS);
+ if (flag & UI_ITEM_R_NO_BG) {
+ layout->emboss = prev_emboss;
+ }
if (flag & UI_ITEM_O_DEPRESS) {
but->flag |= UI_SELECT_DRAW;
@@ -871,7 +961,7 @@ static uiBut *uiItemFullO_ptr_ex(
return but;
}
-static void ui_item_hold_menu(struct bContext *C, ARegion *butregion, uiBut *but)
+static void ui_item_menu_hold(struct bContext *C, ARegion *butregion, uiBut *but)
{
uiPopupMenu *pup = UI_popup_menu_begin(C, "", ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup);
@@ -879,6 +969,24 @@ static void ui_item_hold_menu(struct bContext *C, ARegion *butregion, uiBut *but
UI_popup_menu_but_set(pup, butregion, but);
block->flag |= UI_BLOCK_POPUP_HOLD;
+ block->flag |= UI_BLOCK_IS_FLIP;
+
+ char direction = UI_DIR_DOWN;
+ if (!but->drawstr[0]) {
+ if (butregion->alignment == RGN_ALIGN_LEFT) {
+ direction = UI_DIR_RIGHT;
+ }
+ else if (butregion->alignment == RGN_ALIGN_RIGHT) {
+ direction = UI_DIR_LEFT;
+ }
+ else if (butregion->alignment == RGN_ALIGN_BOTTOM) {
+ direction = UI_DIR_UP;
+ }
+ else {
+ direction = UI_DIR_DOWN;
+ }
+ }
+ UI_block_direction_set(block, direction);
const char *menu_id = but->hold_argN;
MenuType *mt = WM_menutype_find(menu_id, true);
@@ -908,7 +1016,7 @@ void uiItemFullOMenuHold_ptr(
PointerRNA *r_opptr)
{
uiBut *but = uiItemFullO_ptr_ex(layout, ot, name, icon, properties, context, flag, r_opptr);
- UI_but_func_hold_set(but, ui_item_hold_menu, BLI_strdup(menu_id));
+ UI_but_func_hold_set(but, ui_item_menu_hold, BLI_strdup(menu_id));
}
void uiItemFullO(
@@ -1302,8 +1410,10 @@ void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
/* RNA property items */
static void ui_item_rna_size(
- uiLayout *layout, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop,
- int index, bool icon_only, int *r_w, int *r_h)
+ uiLayout *layout, const char *name, int icon,
+ PointerRNA *ptr, PropertyRNA *prop,
+ int index, bool icon_only, bool compact,
+ int *r_w, int *r_h)
{
PropertyType type;
PropertySubType subtype;
@@ -1329,7 +1439,7 @@ static void ui_item_rna_size(
RNA_property_enum_items_gettexted(layout->root->block->evil_C, ptr, prop, &item_array, NULL, &free);
for (item = item_array; item->identifier; item++) {
if (item->identifier[0]) {
- w = max_ii(w, ui_text_icon_width(layout, item->name, item->icon, 0));
+ w = max_ii(w, ui_text_icon_width(layout, item->name, item->icon, compact));
}
}
if (free) {
@@ -1340,12 +1450,13 @@ static void ui_item_rna_size(
if (!w) {
if (type == PROP_ENUM && icon_only) {
- w = ui_text_icon_width(layout, "", ICON_BLANK1, 0);
+ w = ui_text_icon_width(layout, "", ICON_BLANK1, compact);
if (index != RNA_ENUM_VALUE)
w += 0.6f * UI_UNIT_X;
}
else {
- w = ui_text_icon_width(layout, name, icon, 0);
+ /* not compact for float/int buttons, looks too squashed */
+ w = ui_text_icon_width(layout, name, icon, ELEM(type, PROP_FLOAT, PROP_INT) ? false : compact);
}
}
h = UI_UNIT_Y;
@@ -1354,7 +1465,8 @@ static void ui_item_rna_size(
if (index == RNA_NO_INDEX && len > 0) {
if (!name[0] && icon == ICON_NONE)
h = 0;
-
+ if (layout->item.flag & UI_ITEM_PROP_SEP)
+ h = 0;
if (ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER))
h += 2 * UI_UNIT_Y;
else if (subtype == PROP_MATRIX)
@@ -1362,7 +1474,7 @@ static void ui_item_rna_size(
else
h += len * UI_UNIT_Y;
}
- else if (ui_layout_vary_direction(layout) == UI_ITEM_VARY_X) {
+ else if (ui_layout_variable_size(layout)) {
if (type == PROP_BOOLEAN && name[0])
w += UI_UNIT_X / 5;
else if (type == PROP_ENUM && !icon_only)
@@ -1382,8 +1494,22 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
PropertyType type;
char namestr[UI_MAX_NAME_STR];
int len, w, h;
- bool slider, toggle, expand, icon_only, no_bg;
+ bool slider, toggle, expand, icon_only, no_bg, compact;
bool is_array;
+ const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
+
+#ifdef UI_PROP_DECORATE
+ struct {
+ bool use_prop_decorate;
+ int len;
+ uiLayout *layout;
+ uiBut *but;
+ } ui_decorate = {
+ .use_prop_decorate = (
+ ((layout->item.flag & UI_ITEM_PROP_DECORATE) != 0) &&
+ (use_prop_sep && ptr->id.data && id_can_have_animdata(ptr->id.data))),
+ };
+#endif /* UI_PROP_DECORATE */
UI_block_layout_set_current(block, layout);
@@ -1409,13 +1535,24 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
/* pass */
}
else if (ELEM(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER)) {
- name = ui_item_name_add_colon(name, namestr);
+ if (use_prop_sep == false) {
+ name = ui_item_name_add_colon(name, namestr);
+ }
}
else if (type == PROP_BOOLEAN && is_array && index == RNA_NO_INDEX) {
- name = ui_item_name_add_colon(name, namestr);
+ if (use_prop_sep == false) {
+ name = ui_item_name_add_colon(name, namestr);
+ }
}
else if (type == PROP_ENUM && index != RNA_ENUM_VALUE) {
- name = ui_item_name_add_colon(name, namestr);
+ if (flag & UI_ITEM_R_COMPACT) {
+ name = "";
+ }
+ else {
+ if (use_prop_sep == false) {
+ name = ui_item_name_add_colon(name, namestr);
+ }
+ }
}
/* menus and pie-menus don't show checkbox without this */
@@ -1423,13 +1560,24 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
/* use checkboxes only as a fallback in pie-menu's, when no icon is defined */
((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE)))
{
+ int prop_flag = RNA_property_flag(prop);
if (type == PROP_BOOLEAN && ((is_array == false) || (index != RNA_NO_INDEX))) {
- if (is_array) icon = (RNA_property_boolean_get_index(ptr, prop, index)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
- else icon = (RNA_property_boolean_get(ptr, prop)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+ if (prop_flag & PROP_ICONS_CONSECUTIVE) {
+ icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
+ }
+ else if (is_array) {
+ icon = (RNA_property_boolean_get_index(ptr, prop, index)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+ }
+ else {
+ icon = (RNA_property_boolean_get(ptr, prop)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+ }
}
else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) {
int enum_value = RNA_property_enum_get(ptr, prop);
- if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
+ if (prop_flag & PROP_ICONS_CONSECUTIVE) {
+ icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
+ }
+ else if (prop_flag & PROP_ENUM_FLAG) {
icon = (enum_value & value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
}
else {
@@ -1443,16 +1591,111 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
expand = (flag & UI_ITEM_R_EXPAND) != 0;
icon_only = (flag & UI_ITEM_R_ICON_ONLY) != 0;
no_bg = (flag & UI_ITEM_R_NO_BG) != 0;
+ compact = (flag & UI_ITEM_R_COMPACT) != 0;
/* get size */
- ui_item_rna_size(layout, name, icon, ptr, prop, index, icon_only, &w, &h);
+ ui_item_rna_size(layout, name, icon, ptr, prop, index, icon_only, compact, &w, &h);
- if (no_bg)
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ int prev_emboss = layout->emboss;
+ if (no_bg) {
+ layout->emboss = UI_EMBOSS_NONE;
+ }
+
+ /* Split the label / property. */
+ if (use_prop_sep) {
+ uiLayout *layout_row = NULL;
+#ifdef UI_PROP_DECORATE
+ if (ui_decorate.use_prop_decorate) {
+ layout_row = uiLayoutRow(layout, true);
+ layout_row->space = 0;
+ ui_decorate.len = max_ii(1, len);
+ }
+#endif /* UI_PROP_DECORATE */
+
+ if (name[0] == '\0') {
+ /* Ensure we get a column when text is not set. */
+ layout = uiLayoutColumn(layout_row ? layout_row : layout, true);
+ layout->space = 0;
+ }
+ else {
+ const PropertySubType subtype = RNA_property_subtype(prop);
+ uiLayout *layout_split;
+#ifdef UI_PROP_SEP_ICON_WIDTH_EXCEPTION
+ if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) {
+ w = UI_UNIT_X;
+ layout_split = uiLayoutRow(layout_row ? layout_row : layout, true);
+ }
+ else
+#endif /* UI_PROP_SEP_ICON_WIDTH_EXCEPTION */
+ {
+ layout_split = uiLayoutSplit(
+ layout_row ? layout_row : layout,
+ UI_ITEM_PROP_SEP_DIVIDE, true);
+ }
+ layout_split->space = 0;
+ uiLayout *layout_sub = uiLayoutColumn(layout_split, true);
+ layout_sub->space = 0;
+
+ if ((index == RNA_NO_INDEX && is_array) &&
+ ((!expand && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA, PROP_DIRECTION)) == 0))
+ {
+ char name_with_suffix[UI_MAX_DRAW_STR + 2];
+ char str[2] = {'\0'};
+ for (int a = 0; a < len; a++) {
+ str[0] = RNA_property_array_item_char(prop, a);
+ const bool use_prefix = (a == 0 && name && name[0]);
+ if (use_prefix) {
+ char *s = name_with_suffix;
+ s += STRNCPY_RLEN(name_with_suffix, name);
+ *s++ = ' ';
+ *s++ = str[0];
+ *s++ = '\0';
+ }
+ but = uiDefBut(
+ block, UI_BTYPE_LABEL, 0, use_prefix ? name_with_suffix : str,
+ 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ but->drawflag |= UI_BUT_TEXT_RIGHT;
+ but->drawflag &= ~UI_BUT_TEXT_LEFT;
+ }
+ }
+ else {
+ if (name) {
+ but = uiDefBut(
+ block, UI_BTYPE_LABEL, 0, name,
+ 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ but->drawflag |= UI_BUT_TEXT_RIGHT;
+ but->drawflag &= ~UI_BUT_TEXT_LEFT;
+ }
+ }
+
+ /* Watch out! We can only write into the new column now. */
+ layout = uiLayoutColumn(layout_split, true);
+ layout->space = 0;
+ if ((type == PROP_ENUM) && (flag & UI_ITEM_R_EXPAND)) {
+ /* pass (expanded enums each have their own name) */
+ }
+ else {
+ name = "";
+ }
+ }
+
+#ifdef UI_PROP_DECORATE
+ if (ui_decorate.use_prop_decorate) {
+ ui_decorate.layout = uiLayoutColumn(layout_row, true);
+ ui_decorate.layout->space = 0;
+ UI_block_layout_set_current(block, layout);
+ ui_decorate.but = block->buttons.last;
+ }
+#endif /* UI_PROP_DECORATE */
+ }
+ /* End split. */
/* array property */
- if (index == RNA_NO_INDEX && is_array)
- ui_item_array(layout, block, name, icon, ptr, prop, len, 0, 0, w, h, expand, slider, toggle, icon_only);
+ if (index == RNA_NO_INDEX && is_array) {
+ ui_item_array(
+ layout, block, name, icon, ptr, prop, len, 0, 0, w, h,
+ expand, slider, toggle, icon_only, compact, !use_prop_sep);
+ }
/* enum item */
else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) {
if (icon && name[0] && !icon_only)
@@ -1492,8 +1735,43 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
UI_but_flag_enable(but, UI_BUT_LIST_ITEM);
}
- if (no_bg)
- UI_block_emboss_set(block, UI_EMBOSS);
+#ifdef UI_PROP_DECORATE
+ if (ui_decorate.use_prop_decorate) {
+ const bool is_anim = RNA_property_animateable(ptr, prop);
+ uiBut *but_decorate = ui_decorate.but ? ui_decorate.but->next : block->buttons.first;
+ uiLayout *layout_col = uiLayoutColumn(ui_decorate.layout, false);
+ layout_col->space = 0;
+ layout_col->emboss = UI_EMBOSS_NONE;
+ int i;
+ for (i = 0; i < ui_decorate.len && but_decorate; i++) {
+ /* The icons are set in 'ui_but_anim_flag' */
+ if (is_anim) {
+ but = uiDefIconBut(
+ block, UI_BTYPE_BUT, 0, ICON_DOT, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Animate property"));
+ UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL);
+ but->flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK;
+ }
+ else {
+ /* We may show other information here in future, for now use empty space. */
+ but = uiDefIconBut(
+ block, UI_BTYPE_BUT, 0, ICON_BLANK1, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ NULL, 0.0, 0.0, 0.0, 0.0, "");
+ but->flag |= UI_BUT_DISABLED;
+ }
+ /* Order the decorator after the button we decorate, this is used so we can always
+ * do a quick lookup. */
+ BLI_remlink(&block->buttons, but);
+ BLI_insertlinkafter(&block->buttons, but_decorate, but);
+ but_decorate = but->next;
+ }
+ BLI_assert(ELEM(i, 1, ui_decorate.len));
+ }
+#endif /* UI_PROP_DECORATE */
+
+ if (no_bg) {
+ layout->emboss = prev_emboss;
+ }
/* ensure text isn't added to icon_only buttons */
if (but && icon_only) {
@@ -1641,94 +1919,6 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname
/* Pointer RNA button with search */
-typedef struct CollItemSearch {
- struct CollItemSearch *next, *prev;
- char *name;
- int index;
- int iconid;
-} CollItemSearch;
-
-static int sort_search_items_list(const void *a, const void *b)
-{
- const CollItemSearch *cis1 = a;
- const CollItemSearch *cis2 = b;
-
- if (BLI_strcasecmp(cis1->name, cis2->name) > 0)
- return 1;
- else
- return 0;
-}
-
-static void rna_search_cb(const struct bContext *C, void *arg_but, const char *str, uiSearchItems *items)
-{
- uiBut *but = arg_but;
- char *name;
- int i = 0, iconid = 0, flag = RNA_property_flag(but->rnaprop);
- ListBase *items_list = MEM_callocN(sizeof(ListBase), "items_list");
- CollItemSearch *cis;
- const bool skip_filter = !but->changed;
-
- /* build a temporary list of relevant items first */
- RNA_PROP_BEGIN (&but->rnasearchpoin, itemptr, but->rnasearchprop)
- {
- if (flag & PROP_ID_SELF_CHECK)
- if (itemptr.data == but->rnapoin.id.data)
- continue;
-
- /* use filter */
- if (RNA_property_type(but->rnaprop) == PROP_POINTER) {
- if (RNA_property_pointer_poll(&but->rnapoin, but->rnaprop, &itemptr) == 0)
- continue;
- }
-
- if (itemptr.type && RNA_struct_is_ID(itemptr.type)) {
- ID *id = itemptr.data;
- char name_ui[MAX_ID_NAME];
-
-#if 0 /* this name is used for a string comparison and can't be modified, TODO */
- /* if ever enabled, make name_ui be MAX_ID_NAME+1 */
- BKE_id_ui_prefix(name_ui, id);
-#else
- BLI_strncpy(name_ui, id->name + 2, sizeof(name_ui));
-#endif
- name = BLI_strdup(name_ui);
- iconid = ui_id_icon_get(C, id, false);
- }
- else {
- name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); /* could use the string length here */
- iconid = 0;
- }
-
- if (name) {
- if (skip_filter || BLI_strcasestr(name, str)) {
- cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch");
- cis->name = MEM_dupallocN(name);
- cis->index = i;
- cis->iconid = iconid;
- BLI_addtail(items_list, cis);
- }
- MEM_freeN(name);
- }
-
- i++;
- }
- RNA_PROP_END;
-
- BLI_listbase_sort(items_list, sort_search_items_list);
-
- /* add search items from temporary list */
- for (cis = items_list->first; cis; cis = cis->next) {
- if (false == UI_search_item_add(items, cis->name, SET_INT_IN_POINTER(cis->index), cis->iconid)) {
- break;
- }
- }
-
- for (cis = items_list->first; cis; cis = cis->next) {
- MEM_freeN(cis->name);
- }
- BLI_freelistN(items_list);
- MEM_freeN(items_list);
-}
static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA **prop)
{
@@ -1771,6 +1961,8 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN
/* turn button into search button */
if (searchprop) {
+ uiRNACollectionSearch *coll_search = MEM_mallocN(sizeof(*coll_search), __func__);
+
but->type = UI_BTYPE_SEARCH_MENU;
but->hardmax = MAX2(but->hardmax, 256.0f);
but->rnasearchpoin = *searchptr;
@@ -1780,13 +1972,22 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN
but->flag |= UI_BUT_VALUE_CLEAR;
}
+ coll_search->target_ptr = *ptr;
+ coll_search->target_prop = prop;
+ coll_search->search_ptr = *searchptr;
+ coll_search->search_prop = searchprop;
+ coll_search->but_changed = &but->changed;
+
if (RNA_property_type(prop) == PROP_ENUM) {
/* XXX, this will have a menu string,
* but in this case we just want the text */
but->str[0] = 0;
}
- UI_but_func_search_set(but, ui_searchbox_create_generic, rna_search_cb, but, NULL, NULL);
+ UI_but_func_search_set(
+ but, ui_searchbox_create_generic, ui_rna_collection_search_cb,
+ coll_search, NULL, NULL);
+ but->free_search_arg = true;
}
else if (but->type == UI_BTYPE_SEARCH_MENU) {
/* In case we fail to find proper searchprop, so other code might have already set but->type to search menu... */
@@ -1803,6 +2004,7 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna
StructRNA *icontype;
int w, h;
char namestr[UI_MAX_NAME_STR];
+ const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
/* validate arguments */
prop = RNA_struct_find_property(ptr, propname);
@@ -1845,12 +2047,14 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna
if (!name)
name = RNA_property_ui_name(prop);
- name = ui_item_name_add_colon(name, namestr);
+ if (use_prop_sep == false) {
+ name = ui_item_name_add_colon(name, namestr);
+ }
/* create button */
block = uiLayoutGetBlock(layout);
- ui_item_rna_size(layout, name, icon, ptr, prop, 0, 0, &w, &h);
+ ui_item_rna_size(layout, name, icon, ptr, prop, 0, 0, false, &w, &h);
w += UI_UNIT_X; /* X icon needs more space */
but = ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h, 0);
@@ -1868,6 +2072,15 @@ static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
}
+void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt)
+{
+ PanelType *pt = (PanelType *)arg_pt;
+ UI_paneltype_draw(C, pt, layout);
+
+ /* panels are created flipped (from event handling pov) */
+ layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
+}
+
static uiBut *ui_item_menu(
uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN,
const char *tip, bool force_menu)
@@ -1878,9 +2091,6 @@ static uiBut *ui_item_menu(
UI_block_layout_set_current(block, layout);
- if (layout->root->type == UI_LAYOUT_HEADER)
- UI_block_emboss_set(block, UI_EMBOSS);
-
if (!name)
name = "";
if (layout->root->type == UI_LAYOUT_MENU && !icon)
@@ -1890,7 +2100,10 @@ static uiBut *ui_item_menu(
h = UI_UNIT_Y;
if (layout->root->type == UI_LAYOUT_HEADER) { /* ugly .. */
- if (force_menu) {
+ if (icon == ICON_NONE && force_menu) {
+ /* pass */
+ }
+ else if (force_menu) {
w += UI_UNIT_X;
}
else {
@@ -1912,9 +2125,6 @@ static uiBut *ui_item_menu(
but->func_argN = argN;
}
- if (layout->root->type == UI_LAYOUT_HEADER) {
- UI_block_emboss_set(block, UI_EMBOSS);
- }
if (ELEM(layout->root->type, UI_LAYOUT_PANEL, UI_LAYOUT_TOOLBAR) ||
(force_menu && layout->root->type != UI_LAYOUT_MENU)) /* We never want a dropdown in menu! */
{
@@ -1945,6 +2155,95 @@ void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon)
ui_item_menu(layout, name, icon, ui_item_menutype_func, mt, NULL, TIP_(mt->description), false);
}
+/* popover */
+void uiItemPopoverPanel_ptr(uiLayout *layout, bContext *C, PanelType *pt, const char *name, int icon)
+{
+ if (!name) {
+ name = CTX_IFACE_(pt->translation_context, pt->label);
+ }
+
+ if (layout->root->type == UI_LAYOUT_MENU && !icon) {
+ icon = ICON_BLANK1;
+ }
+
+ const bool ok = (pt->poll == NULL) || pt->poll(C, pt);
+ if (ok && (pt->draw_header != NULL)) {
+ layout = uiLayoutRow(layout, true);
+ Panel panel = {
+ .type = pt,
+ .layout = layout,
+ .flag = PNL_POPOVER,
+ };
+ pt->draw_header(C, &panel);
+ }
+ uiBut *but = ui_item_menu(layout, name, icon, ui_item_paneltype_func, pt, NULL, NULL, true);
+ but->type = UI_BTYPE_POPOVER;
+ if (!ok) {
+ but->flag |= UI_BUT_DISABLED;
+ }
+}
+
+void uiItemPopoverPanel(
+ uiLayout *layout, bContext *C,
+ int space_id, int region_id, const char *panel_type,
+ const char *name, int icon)
+{
+ SpaceType *st = BKE_spacetype_from_id(space_id);
+ if (st == NULL) {
+ RNA_warning("space type not found %d", space_id);
+ return;
+ }
+ ARegionType *art = BKE_regiontype_from_id(st, region_id);
+ if (art == NULL) {
+ RNA_warning("region type not found %d", region_id);
+ return;
+ }
+
+ PanelType *pt;
+ for (pt = art->paneltypes.first; pt; pt = pt->next) {
+ if (STREQ(pt->idname, panel_type)) {
+ break;
+ }
+ }
+
+ if (pt == NULL) {
+ RNA_warning("area type not found %s", panel_type);
+ return;
+ }
+
+ uiItemPopoverPanel_ptr(layout, C, pt, name, icon);
+}
+
+void uiItemPopoverPanelFromGroup(
+ uiLayout *layout, bContext *C,
+ int space_id, int region_id, const char *context, const char *category)
+{
+ SpaceType *st = BKE_spacetype_from_id(space_id);
+ if (st == NULL) {
+ RNA_warning("space type not found %d", space_id);
+ return;
+ }
+ ARegionType *art = BKE_regiontype_from_id(st, region_id);
+ if (art == NULL) {
+ RNA_warning("region type not found %d", region_id);
+ return;
+ }
+
+ for (PanelType *pt = art->paneltypes.first; pt; pt = pt->next) {
+ /* Causes too many panels, check context. */
+ if (pt->parent_id[0] == '\0') {
+ if (/* (*context == '\0') || */ STREQ(pt->context, context)) {
+ if ((*category == '\0') || STREQ(pt->category, category)) {
+ if (pt->poll == NULL || pt->poll(C, pt)) {
+ uiItemPopoverPanel_ptr(layout, C, pt, NULL, ICON_NONE);
+ }
+ }
+ }
+ }
+ }
+}
+
+
/* label item */
static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
{
@@ -2035,6 +2334,26 @@ void uiItemS(uiLayout *layout)
uiDefBut(block, (is_menu) ? UI_BTYPE_SEPR_LINE : UI_BTYPE_SEPR, 0, "", 0, 0, space, space, NULL, 0.0, 0.0, 0, 0, "");
}
+/* Flexible spacing. */
+void uiItemSpacer(uiLayout *layout)
+{
+ uiBlock *block = layout->root->block;
+ bool is_menu = ui_block_is_menu(block);
+
+ if (is_menu) {
+ printf("Error: separator_spacer() not supported in menus.\n");
+ return;
+ }
+
+ if (block->direction & UI_DIR_RIGHT) {
+ printf("Error: separator_spacer() only supported in horizontal blocks.\n");
+ return;
+ }
+
+ UI_block_layout_set_current(block, layout);
+ uiDefBut(block, UI_BTYPE_SEPR_SPACER, 0, "", 0, 0, 0.3f * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+}
+
/* level items */
void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg)
{
@@ -2419,7 +2738,7 @@ static bool ui_item_is_radial_displayable(uiItem *item)
static bool ui_item_is_radial_drawable(uiButtonItem *bitem)
{
- if (ELEM(bitem->but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE))
+ if (ELEM(bitem->but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR_SPACER))
return false;
return true;
@@ -2692,6 +3011,364 @@ static void ui_litem_layout_column_flow(uiLayout *litem)
litem->y = miny;
}
+/* multi-column and multi-row layout. */
+typedef struct UILayoutGridFlowInput {
+ /* General layout controll settings. */
+ const bool row_major : 1; /* Fill rows before columns */
+ const bool even_columns : 1; /* All columns will have same width. */
+ const bool even_rows : 1; /* All rows will have same height. */
+ const int space_x; /* Space between columns. */
+ const int space_y; /* Space between rows. */
+ /* Real data about current position and size of this layout item (either estimated, or final values). */
+ const int litem_w; /* Layout item width. */
+ const int litem_x; /* Layout item X position. */
+ const int litem_y; /* Layout item Y position. */
+ /* Actual number of columns and rows to generate (computed from first pass usually). */
+ const int tot_columns; /* Number of columns. */
+ const int tot_rows; /* Number of rows. */
+} UILayoutGridFlowInput;
+
+typedef struct UILayoutGridFlowOutput {
+ int *tot_items; /* Total number of items in this grid layout. */
+ /* Width / X pos data. */
+ float *global_avg_w; /* Computed average width of the columns. */
+ int *cos_x_array; /* Computed X coordinate of each column. */
+ int *widths_array; /* Computed width of each column. */
+ int *tot_w; /* Computed total width. */
+ /* Height / Y pos data. */
+ int *global_max_h; /* Computed height of the tallest item in the grid. */
+ int *cos_y_array; /* Computed Y coordinate of each column. */
+ int *heights_array; /* Computed height of each column. */
+ int *tot_h; /* Computed total height. */
+} UILayoutGridFlowOutput;
+
+static void ui_litem_grid_flow_compute(
+ ListBase *items, UILayoutGridFlowInput *parameters, UILayoutGridFlowOutput *results)
+{
+ uiItem *item;
+ int i;
+
+ float tot_w = 0.0f, tot_h = 0.0f;
+ float global_avg_w = 0.0f, global_totweight_w = 0.0f;
+ int global_max_h = 0;
+
+ float *avg_w = NULL, *totweight_w = NULL;
+ int *max_h = NULL;
+
+ BLI_assert(parameters->tot_columns != 0 || (results->cos_x_array == NULL && results->widths_array == NULL && results->tot_w == NULL));
+ BLI_assert(parameters->tot_rows != 0 || (results->cos_y_array == NULL && results->heights_array == NULL && results->tot_h == NULL));
+
+ if (results->tot_items) {
+ *results->tot_items = 0;
+ }
+
+ if (items->first == NULL) {
+ if (results->global_avg_w) {
+ *results->global_avg_w = 0.0f;
+ }
+ if (results->global_max_h) {
+ *results->global_max_h = 0;
+ }
+ return;
+ }
+
+ if (parameters->tot_columns != 0) {
+ avg_w = BLI_array_alloca(avg_w, parameters->tot_columns);
+ totweight_w = BLI_array_alloca(totweight_w, parameters->tot_columns);
+ memset(avg_w, 0, sizeof(*avg_w) * parameters->tot_columns);
+ memset(totweight_w, 0, sizeof(*totweight_w) * parameters->tot_columns);
+ }
+ if (parameters->tot_rows != 0) {
+ max_h = BLI_array_alloca(max_h, parameters->tot_rows);
+ memset(max_h, 0, sizeof(*max_h) * parameters->tot_rows);
+ }
+
+ for (i = 0, item = items->first; item; item = item->next, i++) {
+ int item_w, item_h;
+ ui_item_size(item, &item_w, &item_h);
+
+ global_avg_w += (float)(item_w * item_w);
+ global_totweight_w += (float)item_w;
+ global_max_h = max_ii(global_max_h, item_h);
+
+ if (parameters->tot_rows != 0 && parameters->tot_columns != 0) {
+ const int index_col = parameters->row_major ? i % parameters->tot_columns : i / parameters->tot_rows;
+ const int index_row = parameters->row_major ? i / parameters->tot_columns : i % parameters->tot_rows;
+
+ avg_w[index_col] += (float)(item_w * item_w);
+ totweight_w[index_col] += (float)item_w;
+
+ max_h[index_row] = max_ii(max_h[index_row], item_h);
+ }
+
+ if (results->tot_items) {
+ (*results->tot_items)++;
+ }
+ }
+
+ /* Finalize computing of column average sizes */
+ global_avg_w /= global_totweight_w;
+ if (parameters->tot_columns != 0) {
+ for (i = 0; i < parameters->tot_columns; i++) {
+ avg_w[i] /= totweight_w[i];
+ tot_w += avg_w[i];
+ }
+ if (parameters->even_columns) {
+ tot_w = ceilf(global_avg_w) * parameters->tot_columns;
+ }
+ }
+ /* Finalize computing of rows max sizes */
+ if (parameters->tot_rows != 0) {
+ for (i = 0; i < parameters->tot_rows; i++) {
+ tot_h += max_h[i];
+ }
+ if (parameters->even_rows) {
+ tot_h = global_max_h * parameters->tot_columns;
+ }
+ }
+
+ /* Compute positions and sizes of all cells. */
+ if (results->cos_x_array != NULL && results->widths_array != NULL) {
+ /* We enlarge/narrow columns evenly to match available width. */
+ const float wfac = (float)(parameters->litem_w - (parameters->tot_columns - 1) * parameters->space_x) / tot_w;
+
+ for (int col = 0; col < parameters->tot_columns; col++) {
+ results->cos_x_array[col] = (
+ col ?
+ results->cos_x_array[col - 1] + results->widths_array[col - 1] + parameters->space_x :
+ parameters->litem_x
+ );
+ if (parameters->even_columns) {
+ /* (< remaining width > - < space between remaining columns >) / < remaining columns > */
+ results->widths_array[col] = (
+ ((parameters->litem_w - (results->cos_x_array[col] - parameters->litem_x)) -
+ (parameters->tot_columns - col - 1) * parameters->space_x) / (parameters->tot_columns - col));
+ }
+ else if (col == parameters->tot_columns - 1) {
+ /* Last column copes width rounding errors... */
+ results->widths_array[col] = parameters->litem_w - (results->cos_x_array[col] - parameters->litem_x);
+ }
+ else {
+ results->widths_array[col] = (int)(avg_w[col] * wfac);
+ }
+ }
+ }
+ if (results->cos_y_array != NULL && results->heights_array != NULL) {
+ for (int row = 0; row < parameters->tot_rows; row++) {
+ if (parameters->even_rows) {
+ results->heights_array[row] = global_max_h;
+ }
+ else {
+ results->heights_array[row] = max_h[row];
+ }
+ results->cos_y_array[row] = (
+ row ?
+ results->cos_y_array[row - 1] - parameters->space_y - results->heights_array[row] :
+ parameters->litem_y - results->heights_array[row]);
+ }
+ }
+
+ if (results->global_avg_w) {
+ *results->global_avg_w = global_avg_w;
+ }
+ if (results->global_max_h) {
+ *results->global_max_h = global_max_h;
+ }
+ if (results->tot_w) {
+ *results->tot_w = (int)tot_w + parameters->space_x * (parameters->tot_columns - 1);
+ }
+ if (results->tot_h) {
+ *results->tot_h = tot_h + parameters->space_y * (parameters->tot_rows - 1);
+ }
+}
+
+static void ui_litem_estimate_grid_flow(uiLayout *litem)
+{
+ uiStyle *style = litem->root->style;
+ uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem;
+
+ const int space_x = style->columnspace;
+ const int space_y = style->buttonspacey;
+
+ /* Estimate average needed width and height per item. */
+ {
+ float avg_w;
+ int max_h;
+
+ ui_litem_grid_flow_compute(
+ &litem->items,
+ &((UILayoutGridFlowInput) {
+ .row_major = gflow->row_major,
+ .even_columns = gflow->even_columns,
+ .even_rows = gflow->even_rows,
+ .litem_w = litem->w,
+ .litem_x = litem->x,
+ .litem_y = litem->y,
+ .space_x = space_x,
+ .space_y = space_y,
+ }),
+ &((UILayoutGridFlowOutput) {
+ .tot_items = &gflow->tot_items,
+ .global_avg_w = &avg_w,
+ .global_max_h = &max_h,
+ }));
+
+ if (gflow->tot_items == 0) {
+ litem->w = litem->h = 0;
+ gflow->tot_columns = gflow->tot_rows = 0;
+ return;
+ }
+
+ /* Even in varying column width case, we fix our columns number from weighted average width of items,
+ * a proper solving of required width would be too costly, and this should give reasonably good results
+ * in all resonable cases... */
+ if (gflow->columns_len > 0) {
+ gflow->tot_columns = gflow->columns_len;
+ }
+ else {
+ if (avg_w == 0.0f) {
+ gflow->tot_columns = 1;
+ }
+ else {
+ gflow->tot_columns = min_ii(max_ii((int)(litem->w / avg_w), 1), gflow->tot_items);
+ }
+ }
+ gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns);
+
+ /* Try to tweak number of columns and rows to get better filling of last column or row,
+ * and apply 'modulo' value to number of columns or rows.
+ * Note that modulo does not prevent ending with fewer columns/rows than modulo, if mandatory
+ * to avoid empty column/row. */
+ {
+ const int modulo = (gflow->columns_len < -1) ? -gflow->columns_len : 0;
+ const int step = modulo ? modulo : 1;
+
+ if (gflow->row_major) {
+ /* Adjust number of columns to be mutiple of given modulo. */
+ if (modulo && gflow->tot_columns % modulo != 0 && gflow->tot_columns > modulo) {
+ gflow->tot_columns = gflow->tot_columns - (gflow->tot_columns % modulo);
+ }
+ /* Find smallest number of columns conserving computed optimal number of rows. */
+ for (gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns);
+ (gflow->tot_columns - step) > 0 &&
+ (int)ceilf((float)gflow->tot_items / (gflow->tot_columns - step)) <= gflow->tot_rows;
+ gflow->tot_columns -= step);
+ }
+ else {
+ /* Adjust number of rows to be mutiple of given modulo. */
+ if (modulo && gflow->tot_rows % modulo != 0) {
+ gflow->tot_rows = min_ii(gflow->tot_rows + modulo - (gflow->tot_rows % modulo), gflow->tot_items);
+ }
+ /* Find smallest number of rows conserving computed optimal number of columns. */
+ for (gflow->tot_columns = (int)ceilf((float)gflow->tot_items / gflow->tot_rows);
+ (gflow->tot_rows - step) > 0 &&
+ (int)ceilf((float)gflow->tot_items / (gflow->tot_rows - step)) <= gflow->tot_columns;
+ gflow->tot_rows -= step);
+ }
+ }
+
+ /* Set evenly-spaced axes size (quick optimization in case we have even columns and rows). */
+ if (gflow->even_columns && gflow->even_rows) {
+ litem->w = (int)(gflow->tot_columns * avg_w) + space_x * (gflow->tot_columns - 1);
+ litem->h = (int)(gflow->tot_rows * max_h) + space_y * (gflow->tot_rows - 1);
+ return;
+ }
+ }
+
+ /* Now that we have our final number of columns and rows,
+ * we can compute actual needed space for non-evenly sized axes. */
+ {
+ int tot_w, tot_h;
+
+ ui_litem_grid_flow_compute(
+ &litem->items,
+ &((UILayoutGridFlowInput) {
+ .row_major = gflow->row_major,
+ .even_columns = gflow->even_columns,
+ .even_rows = gflow->even_rows,
+ .litem_w = litem->w,
+ .litem_x = litem->x,
+ .litem_y = litem->y,
+ .space_x = space_x,
+ .space_y = space_y,
+ .tot_columns = gflow->tot_columns,
+ .tot_rows = gflow->tot_rows,
+ }),
+ &((UILayoutGridFlowOutput) {
+ .tot_w = &tot_w,
+ .tot_h = &tot_h,
+ }));
+
+ litem->w = tot_w;
+ litem->h = tot_h;
+ }
+}
+
+static void ui_litem_layout_grid_flow(uiLayout *litem)
+{
+ int i;
+ uiStyle *style = litem->root->style;
+ uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem;
+ uiItem *item;
+
+ if (gflow->tot_items == 0) {
+ litem->w = litem->h = 0;
+ return;
+ }
+
+ BLI_assert(gflow->tot_columns > 0);
+ BLI_assert(gflow->tot_rows > 0);
+
+ const int space_x = style->columnspace;
+ const int space_y = style->buttonspacey;
+
+ int *widths = BLI_array_alloca(widths, gflow->tot_columns);
+ int *heights = BLI_array_alloca(heights, gflow->tot_rows);
+ int *cos_x = BLI_array_alloca(cos_x, gflow->tot_columns);
+ int *cos_y = BLI_array_alloca(cos_y, gflow->tot_rows);
+
+ /* This time we directly compute coordinates and sizes of all cells. */
+ ui_litem_grid_flow_compute(
+ &litem->items,
+ &((UILayoutGridFlowInput) {
+ .row_major = gflow->row_major,
+ .even_columns = gflow->even_columns,
+ .even_rows = gflow->even_rows,
+ .litem_w = litem->w,
+ .litem_x = litem->x,
+ .litem_y = litem->y,
+ .space_x = space_x,
+ .space_y = space_y,
+ .tot_columns = gflow->tot_columns,
+ .tot_rows = gflow->tot_rows,
+ }),
+ &((UILayoutGridFlowOutput) {
+ .cos_x_array = cos_x,
+ .cos_y_array = cos_y,
+ .widths_array = widths,
+ .heights_array = heights,
+ }));
+
+ for (item = litem->items.first, i = 0; item; item = item->next, i++) {
+ const int col = gflow->row_major ? i % gflow->tot_columns : i / gflow->tot_rows;
+ const int row = gflow->row_major ? i / gflow->tot_columns : i % gflow->tot_rows;
+ int item_w, item_h;
+ ui_item_size(item, &item_w, &item_h);
+
+ const int w = widths[col];
+ const int h = heights[row];
+
+ item_w = (litem->alignment == UI_LAYOUT_ALIGN_EXPAND) ? w : min_ii(w, item_w);
+ item_h = (litem->alignment == UI_LAYOUT_ALIGN_EXPAND) ? h : min_ii(h, item_h);
+
+ ui_item_position(item, cos_x[col], cos_y[row], item_w, item_h);
+ }
+
+ litem->h = litem->y - cos_y[gflow->tot_rows - 1];
+ litem->x = (cos_x[gflow->tot_columns - 1] - litem->x) + widths[gflow->tot_columns - 1];
+ litem->y = litem->y - litem->h;
+}
+
/* free layout */
static void ui_litem_estimate_absolute(uiLayout *litem)
{
@@ -2861,22 +3538,32 @@ static void ui_litem_layout_overlap(uiLayout *litem)
litem->y = y - litem->h;
}
-/* layout create functions */
-uiLayout *uiLayoutRow(uiLayout *layout, bool align)
+static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int align)
{
- uiLayout *litem;
-
- litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
- litem->item.type = ITEM_LAYOUT_ROW;
litem->root = layout->root;
litem->align = align;
+ /* Children of gridflow layout shall never have "ideal big size" returned as estimated size. */
+ litem->variable_size = layout->variable_size || layout->item.type == ITEM_LAYOUT_GRID_FLOW;
litem->active = true;
litem->enabled = true;
litem->context = layout->context;
- litem->space = (align) ? 0 : layout->root->style->buttonspacex;
litem->redalert = layout->redalert;
litem->w = layout->w;
+ litem->emboss = layout->emboss;
+ litem->item.flag = (layout->item.flag & (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE));
BLI_addtail(&layout->items, litem);
+}
+
+/* layout create functions */
+uiLayout *uiLayoutRow(uiLayout *layout, bool align)
+{
+ uiLayout *litem;
+
+ litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
+ ui_litem_init_from_parent(litem, layout, align);
+
+ litem->item.type = ITEM_LAYOUT_ROW;
+ litem->space = (align) ? 0 : layout->root->style->buttonspacex;
UI_block_layout_set_current(layout->root->block, litem);
@@ -2888,16 +3575,10 @@ uiLayout *uiLayoutColumn(uiLayout *layout, bool align)
uiLayout *litem;
litem = MEM_callocN(sizeof(uiLayout), "uiLayoutColumn");
+ ui_litem_init_from_parent(litem, layout, align);
+
litem->item.type = ITEM_LAYOUT_COLUMN;
- litem->root = layout->root;
- litem->align = align;
- litem->active = true;
- litem->enabled = true;
- litem->context = layout->context;
- litem->space = (litem->align) ? 0 : layout->root->style->buttonspacey;
- litem->redalert = layout->redalert;
- litem->w = layout->w;
- BLI_addtail(&layout->items, litem);
+ litem->space = (align) ? 0 : layout->root->style->buttonspacey;
UI_block_layout_set_current(layout->root->block, litem);
@@ -2909,17 +3590,31 @@ uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align)
uiLayoutItemFlow *flow;
flow = MEM_callocN(sizeof(uiLayoutItemFlow), "uiLayoutItemFlow");
+ ui_litem_init_from_parent(&flow->litem, layout, align);
+
flow->litem.item.type = ITEM_LAYOUT_COLUMN_FLOW;
- flow->litem.root = layout->root;
- flow->litem.align = align;
- flow->litem.active = true;
- flow->litem.enabled = true;
- flow->litem.context = layout->context;
flow->litem.space = (flow->litem.align) ? 0 : layout->root->style->columnspace;
- flow->litem.redalert = layout->redalert;
- flow->litem.w = layout->w;
flow->number = number;
- BLI_addtail(&layout->items, flow);
+
+ UI_block_layout_set_current(layout->root->block, &flow->litem);
+
+ return &flow->litem;
+}
+
+uiLayout *uiLayoutGridFlow(
+ uiLayout *layout, bool row_major, int columns_len, bool even_columns, bool even_rows, bool align)
+{
+ uiLayoutItemGridFlow *flow;
+
+ flow = MEM_callocN(sizeof(uiLayoutItemGridFlow), __func__);
+ flow->litem.item.type = ITEM_LAYOUT_GRID_FLOW;
+ ui_litem_init_from_parent(&flow->litem, layout, align);
+
+ flow->litem.space = (flow->litem.align) ? 0 : layout->root->style->columnspace;
+ flow->row_major = row_major;
+ flow->columns_len = columns_len;
+ flow->even_columns = even_columns;
+ flow->even_rows = even_rows;
UI_block_layout_set_current(layout->root->block, &flow->litem);
@@ -2931,15 +3626,10 @@ static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type)
uiLayoutItemBx *box;
box = MEM_callocN(sizeof(uiLayoutItemBx), "uiLayoutItemBx");
+ ui_litem_init_from_parent(&box->litem, layout, false);
+
box->litem.item.type = ITEM_LAYOUT_BOX;
- box->litem.root = layout->root;
- box->litem.active = 1;
- box->litem.enabled = 1;
- box->litem.context = layout->context;
box->litem.space = layout->root->style->columnspace;
- box->litem.redalert = layout->redalert;
- box->litem.w = layout->w;
- BLI_addtail(&layout->items, box);
UI_block_layout_set_current(layout->root->block, &box->litem);
@@ -2967,14 +3657,9 @@ uiLayout *uiLayoutRadial(uiLayout *layout)
}
litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRadial");
+ ui_litem_init_from_parent(litem, layout, false);
+
litem->item.type = ITEM_LAYOUT_RADIAL;
- litem->root = layout->root;
- litem->active = true;
- litem->enabled = true;
- litem->context = layout->context;
- litem->redalert = layout->redalert;
- litem->w = layout->w;
- BLI_addtail(&layout->root->layout->items, litem);
UI_block_layout_set_current(layout->root->block, litem);
@@ -3031,14 +3716,9 @@ uiLayout *uiLayoutAbsolute(uiLayout *layout, bool align)
uiLayout *litem;
litem = MEM_callocN(sizeof(uiLayout), "uiLayoutAbsolute");
+ ui_litem_init_from_parent(litem, layout, align);
+
litem->item.type = ITEM_LAYOUT_ABSOLUTE;
- litem->root = layout->root;
- litem->align = align;
- litem->active = 1;
- litem->enabled = 1;
- litem->context = layout->context;
- litem->redalert = layout->redalert;
- BLI_addtail(&layout->items, litem);
UI_block_layout_set_current(layout->root->block, litem);
@@ -3060,13 +3740,9 @@ uiLayout *uiLayoutOverlap(uiLayout *layout)
uiLayout *litem;
litem = MEM_callocN(sizeof(uiLayout), "uiLayoutOverlap");
+ ui_litem_init_from_parent(litem, layout, false);
+
litem->item.type = ITEM_LAYOUT_OVERLAP;
- litem->root = layout->root;
- litem->active = true;
- litem->enabled = true;
- litem->context = layout->context;
- litem->redalert = layout->redalert;
- BLI_addtail(&layout->items, litem);
UI_block_layout_set_current(layout->root->block, litem);
@@ -3078,17 +3754,11 @@ uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, bool align)
uiLayoutItemSplit *split;
split = MEM_callocN(sizeof(uiLayoutItemSplit), "uiLayoutItemSplit");
+ ui_litem_init_from_parent(&split->litem, layout, align);
+
split->litem.item.type = ITEM_LAYOUT_SPLIT;
- split->litem.root = layout->root;
- split->litem.align = align;
- split->litem.active = true;
- split->litem.enabled = true;
- split->litem.context = layout->context;
split->litem.space = layout->root->style->columnspace;
- split->litem.redalert = layout->redalert;
- split->litem.w = layout->w;
split->percentage = percentage;
- BLI_addtail(&layout->items, split);
UI_block_layout_set_current(layout->root->block, &split->litem);
@@ -3130,6 +3800,31 @@ void uiLayoutSetScaleY(uiLayout *layout, float scale)
layout->scale[1] = scale;
}
+void uiLayoutSetEmboss(uiLayout *layout, char emboss)
+{
+ layout->emboss = emboss;
+}
+
+bool uiLayoutGetPropSep(uiLayout *layout)
+{
+ return (layout->item.flag & UI_ITEM_PROP_SEP) != 0;
+}
+
+void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
+{
+ SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_SEP);
+}
+
+bool uiLayoutGetPropDecorate(uiLayout *layout)
+{
+ return (layout->item.flag & UI_ITEM_PROP_DECORATE) != 0;
+}
+
+void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
+{
+ SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_DECORATE);
+}
+
bool uiLayoutGetActive(uiLayout *layout)
{
return layout->active;
@@ -3170,6 +3865,16 @@ float uiLayoutGetScaleY(uiLayout *layout)
return layout->scale[1];
}
+int uiLayoutGetEmboss(uiLayout *layout)
+{
+ if (layout->emboss == UI_EMBOSS_UNDEFINED) {
+ return layout->root->block->dt;
+ }
+ else {
+ return layout->emboss;
+ }
+}
+
/********************** Layout *******************/
static void ui_item_scale(uiLayout *litem, const float scale[2])
@@ -3178,6 +3883,11 @@ static void ui_item_scale(uiLayout *litem, const float scale[2])
int x, y, w, h;
for (item = litem->items.last; item; item = item->prev) {
+ if (item->type != ITEM_BUTTON) {
+ uiLayout *subitem = (uiLayout *)item;
+ ui_item_scale(subitem, scale);
+ }
+
ui_item_size(item, &w, &h);
ui_item_offset(item, &x, &y);
@@ -3221,6 +3931,9 @@ static void ui_item_estimate(uiItem *item)
case ITEM_LAYOUT_COLUMN_FLOW:
ui_litem_estimate_column_flow(litem);
break;
+ case ITEM_LAYOUT_GRID_FLOW:
+ ui_litem_estimate_grid_flow(litem);
+ break;
case ITEM_LAYOUT_ROW:
ui_litem_estimate_row(litem);
break;
@@ -3320,6 +4033,9 @@ static void ui_item_layout(uiItem *item)
case ITEM_LAYOUT_COLUMN_FLOW:
ui_litem_layout_column_flow(litem);
break;
+ case ITEM_LAYOUT_GRID_FLOW:
+ ui_litem_layout_grid_flow(litem);
+ break;
case ITEM_LAYOUT_ROW:
ui_litem_layout_row(litem);
break;
@@ -3416,6 +4132,9 @@ uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int s
layout = MEM_callocN(sizeof(uiLayout), "uiLayout");
layout->item.type = ITEM_LAYOUT_ROOT;
+ /* Only used when 'UI_ITEM_PROP_SEP' is set. */
+ layout->item.flag = UI_ITEM_PROP_DECORATE;
+
layout->x = x;
layout->y = y;
layout->root = root;
@@ -3423,10 +4142,15 @@ uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int s
layout->active = 1;
layout->enabled = 1;
layout->context = NULL;
+ layout->emboss = UI_EMBOSS_UNDEFINED;
if (type == UI_LAYOUT_MENU || type == UI_LAYOUT_PIEMENU)
layout->space = 0;
+ if (type == UI_LAYOUT_TOOLBAR) {
+ block->flag |= UI_BLOCK_SHOW_SHORTCUT_ALWAYS;
+ }
+
if (dir == UI_LAYOUT_HORIZONTAL) {
layout->h = size;
layout->root->emh = em * UI_UNIT_Y;
@@ -3483,6 +4207,10 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but)
but->context = layout->context;
but->context->used = true;
}
+
+ if (layout->emboss != UI_EMBOSS_UNDEFINED) {
+ but->dt = layout->emboss;
+ }
}
void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext)
@@ -3562,6 +4290,18 @@ MenuType *UI_but_menutype_get(uiBut *but)
}
}
+/* this is a bit of a hack but best keep it in one place at least */
+PanelType *UI_but_paneltype_get(uiBut *but)
+{
+ if (but->menu_create_func == ui_item_paneltype_func) {
+ return (PanelType *)but->poin;
+ }
+ else {
+ return NULL;
+ }
+}
+
+
void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout)
{
Menu menu = {
@@ -3583,3 +4323,64 @@ void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout)
CTX_store_set(C, NULL);
}
}
+
+
+static void ui_paneltype_draw_impl(
+ bContext *C, PanelType *pt, uiLayout *layout, bool show_header)
+{
+ Panel *panel = MEM_callocN(sizeof(Panel), "popover panel");
+ panel->type = pt;
+ panel->flag = PNL_POPOVER;
+
+ uiLayout *last_item = layout->items.last;
+
+ /* Draw main panel. */
+ if (show_header) {
+ uiLayout *row = uiLayoutRow(layout, false);
+ if (pt->draw_header) {
+ panel->layout = row;
+ pt->draw_header(C, panel);
+ panel->layout = NULL;
+ }
+ uiItemL(row, pt->label, ICON_NONE);
+ }
+
+ panel->layout = layout;
+ pt->draw(C, panel);
+ panel->layout = NULL;
+
+ MEM_freeN(panel);
+
+ /* Draw child panels. */
+ for (LinkData *link = pt->children.first; link; link = link->next) {
+ PanelType *child_pt = link->data;
+
+ if (child_pt->poll == NULL || child_pt->poll(C, child_pt)) {
+ /* Add space if something was added to the layout. */
+ if (last_item != layout->items.last) {
+ uiItemS(layout);
+ last_item = layout->items.last;
+ }
+
+ uiLayout *col = uiLayoutColumn(layout, false);
+ ui_paneltype_draw_impl(C, child_pt, col, true);
+ }
+ }
+}
+
+/**
+ * Used for popup panels only.
+ */
+void UI_paneltype_draw(bContext *C, PanelType *pt, uiLayout *layout)
+{
+ if (layout->context) {
+ CTX_store_set(C, layout->context);
+ }
+
+ ui_paneltype_draw_impl(C, pt, layout, false);
+
+ if (layout->context) {
+ CTX_store_set(C, NULL);
+ }
+
+}
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 9a4ea41141a..96128aa29f0 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -42,14 +42,20 @@
#include "BLT_lang.h"
#include "BKE_context.h"
+#include "BKE_idprop.h"
+#include "BKE_layer.h"
#include "BKE_screen.h"
#include "BKE_global.h"
+#include "BKE_library_override.h"
#include "BKE_node.h"
#include "BKE_text.h" /* for UI_OT_reports_to_text */
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_types.h"
#include "UI_interface.h"
@@ -328,6 +334,217 @@ static void UI_OT_unset_property_button(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO;
}
+
+/* Note that we use different values for UI/UX than 'real' override operations, user does not care
+ * whether it's added or removed for the differential operation e.g. */
+enum {
+ UIOverride_Type_NOOP = 0,
+ UIOverride_Type_Replace = 1,
+ UIOverride_Type_Difference = 2, /* Add/subtract */
+ UIOverride_Type_Factor = 3, /* Multiply */
+ /* TODO: should/can we expose insert/remove ones for collections? Doubt it... */
+};
+
+static EnumPropertyItem override_type_items[] = {
+ {UIOverride_Type_NOOP, "NOOP", 0, "NoOp",
+ "'No-Operation', place holder preventing automatic override to ever affect the property"},
+ {UIOverride_Type_Replace, "REPLACE", 0, "Replace", "Completely replace value from linked data by local one"},
+ {UIOverride_Type_Difference, "DIFFERENCE", 0, "Difference", "Store difference to linked data value"},
+ {UIOverride_Type_Factor, "FACTOR", 0, "Factor", "Store factor to linked data value (useful e.g. for scale)"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+
+static bool override_type_set_button_poll(bContext *C)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ const int override_status = RNA_property_static_override_status(&ptr, prop, index);
+
+ return (ptr.data && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE));
+}
+
+static int override_type_set_button_exec(bContext *C, wmOperator *op)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ bool created;
+ const bool all = RNA_boolean_get(op->ptr, "all");
+ const int op_type = RNA_enum_get(op->ptr, "type");
+
+ short operation;
+
+ switch (op_type) {
+ case UIOverride_Type_NOOP:
+ operation = IDOVERRIDESTATIC_OP_NOOP;
+ break;
+ case UIOverride_Type_Replace:
+ operation = IDOVERRIDESTATIC_OP_REPLACE;
+ break;
+ case UIOverride_Type_Difference:
+ operation = IDOVERRIDESTATIC_OP_ADD; /* override code will automatically switch to subtract if needed. */
+ break;
+ case UIOverride_Type_Factor:
+ operation = IDOVERRIDESTATIC_OP_MULTIPLY;
+ break;
+ default:
+ operation = IDOVERRIDESTATIC_OP_REPLACE;
+ BLI_assert(0);
+ break;
+ }
+
+ /* try to reset the nominated setting to its default value */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ BLI_assert(ptr.id.data != NULL);
+
+ if (all) {
+ index = -1;
+ }
+
+ IDOverrideStaticPropertyOperation *opop = RNA_property_override_property_operation_get(
+ &ptr, prop, operation, index, true, NULL, &created);
+ if (!created) {
+ opop->operation = operation;
+ }
+
+ return operator_button_property_finish(C, &ptr, prop);
+}
+
+static int override_type_set_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+#if 0 /* Disabled for now */
+ return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
+#else
+ RNA_enum_set(op->ptr, "type", IDOVERRIDESTATIC_OP_REPLACE);
+ return override_type_set_button_exec(C, op);
+#endif
+}
+
+static void UI_OT_override_type_set_button(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Define Override Type";
+ ot->idname = "UI_OT_override_type_set_button";
+ ot->description = "Create an override operation, or set the type of an existing one";
+
+ /* callbacks */
+ ot->poll = override_type_set_button_poll;
+ ot->exec = override_type_set_button_exec;
+ ot->invoke = override_type_set_button_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", override_type_items, UIOverride_Type_Replace,
+ "Type", "Type of override operation");
+ /* TODO: add itemf callback, not all options are available for all data types... */
+}
+
+
+static bool override_remove_button_poll(bContext *C)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ const int override_status = RNA_property_static_override_status(&ptr, prop, index);
+
+ return (ptr.data && ptr.id.data && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN));
+}
+
+static int override_remove_button_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ PointerRNA ptr, id_refptr, src;
+ PropertyRNA *prop;
+ int index;
+ const bool all = RNA_boolean_get(op->ptr, "all");
+
+ /* try to reset the nominated setting to its default value */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ ID *id = ptr.id.data;
+ IDOverrideStaticProperty *oprop = RNA_property_override_property_find(&ptr, prop);
+ BLI_assert(oprop != NULL);
+ BLI_assert(id != NULL && id->override_static != NULL);
+
+ const bool is_template = (id->override_static->reference == NULL);
+
+ /* We need source (i.e. linked data) to restore values of deleted overrides...
+ * If this is an override template, we obviously do not need to restore anything. */
+ if (!is_template) {
+ RNA_id_pointer_create(id->override_static->reference, &id_refptr);
+ if (!RNA_path_resolve(&id_refptr, oprop->rna_path, &src, NULL)) {
+ BLI_assert(0 && "Failed to create matching source (linked data) RNA pointer");
+ }
+ }
+
+ if (!all && index != -1) {
+ bool is_strict_find;
+ /* Remove override operation for given item, add singular operations for the other items as needed. */
+ IDOverrideStaticPropertyOperation *opop = BKE_override_static_property_operation_find(
+ oprop, NULL, NULL, index, index, false, &is_strict_find);
+ BLI_assert(opop != NULL);
+ if (!is_strict_find) {
+ /* No specific override operation, we have to get generic one,
+ * and create item-specific override operations for all but given index, before removing generic one. */
+ for (int idx = RNA_property_array_length(&ptr, prop); idx--; ) {
+ if (idx != index) {
+ BKE_override_static_property_operation_get(oprop, opop->operation, NULL, NULL, idx, idx, true, NULL, NULL);
+ }
+ }
+ }
+ BKE_override_static_property_operation_delete(oprop, opop);
+ if (!is_template) {
+ RNA_property_copy(bmain, &ptr, &src, prop, index);
+ }
+ if (BLI_listbase_is_empty(&oprop->operations)) {
+ BKE_override_static_property_delete(id->override_static, oprop);
+ }
+ }
+ else {
+ /* Just remove whole generic override operation of this property. */
+ BKE_override_static_property_delete(id->override_static, oprop);
+ if (!is_template) {
+ RNA_property_copy(bmain, &ptr, &src, prop, -1);
+ }
+ }
+
+ return operator_button_property_finish(C, &ptr, prop);
+}
+
+static void UI_OT_override_remove_button(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Override";
+ ot->idname = "UI_OT_override_remove_button";
+ ot->description = "Remove an override operation";
+
+ /* callbacks */
+ ot->poll = override_remove_button_poll;
+ ot->exec = override_remove_button_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
+}
+
+
+
+
/* Copy To Selected Operator ------------------------ */
bool UI_context_copy_to_selected_list(
@@ -484,6 +701,7 @@ bool UI_context_copy_to_selected_list(
*/
static bool copy_to_selected_button(bContext *C, bool all, bool poll)
{
+ Main *bmain = CTX_data_main(C);
PointerRNA ptr, lptr, idptr;
PropertyRNA *prop, *lprop;
bool success = false;
@@ -532,7 +750,7 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll)
break;
}
else {
- if (RNA_property_copy(&lptr, &ptr, prop, (all) ? -1 : index)) {
+ if (RNA_property_copy(bmain, &lptr, &ptr, prop, (all) ? -1 : index)) {
RNA_property_update(C, &lptr, prop);
success = true;
}
@@ -792,6 +1010,7 @@ static int editsource_exec(bContext *C, wmOperator *op)
ui_editsource_active_but_set(but);
/* redraw and get active button python info */
+ ED_region_do_layout(C, ar);
ED_region_do_draw(C, ar);
ar->do_draw = false;
@@ -1127,6 +1346,8 @@ void ED_operatortypes_ui(void)
WM_operatortype_append(UI_OT_copy_python_command_button);
WM_operatortype_append(UI_OT_reset_default_button);
WM_operatortype_append(UI_OT_unset_property_button);
+ WM_operatortype_append(UI_OT_override_type_set_button);
+ WM_operatortype_append(UI_OT_override_remove_button);
WM_operatortype_append(UI_OT_copy_to_selected_button);
WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */
WM_operatortype_append(UI_OT_drop_color);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 744f6b3c4d0..79d92eedfa3 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -50,9 +50,6 @@
#include "BKE_context.h"
#include "BKE_screen.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
#include "BLF_api.h"
#include "WM_api.h"
@@ -65,6 +62,9 @@
#include "UI_interface_icons.h"
#include "UI_resources.h"
+#include "GPU_immediate.h"
+#include "GPU_state.h"
+
#include "interface_intern.h"
/*********************** defines and structs ************************/
@@ -111,17 +111,23 @@ typedef struct uiHandlePanelData {
int startsizex, startsizey;
} uiHandlePanelData;
+static int get_panel_real_size_y(const Panel *pa);
static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelState state);
/*********************** space specific code ************************/
/* temporary code to remove all sbuts stuff from panel code */
+/* SpaceButs.align */
+typedef enum eSpaceButtons_Align {
+ BUT_HORIZONTAL = 0,
+ BUT_VERTICAL = 1,
+ BUT_AUTO = 2,
+} eSpaceButtons_Align;
+
static int panel_aligned(ScrArea *sa, ARegion *ar)
{
- if (sa->spacetype == SPACE_BUTS && ar->regiontype == RGN_TYPE_WINDOW) {
- SpaceButs *sbuts = sa->spacedata.first;
- return sbuts->align;
- }
+ if (sa->spacetype == SPACE_BUTS && ar->regiontype == RGN_TYPE_WINDOW)
+ return BUT_VERTICAL;
else if (sa->spacetype == SPACE_USERPREF && ar->regiontype == RGN_TYPE_WINDOW)
return BUT_VERTICAL;
else if (sa->spacetype == SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS)
@@ -134,45 +140,78 @@ static int panel_aligned(ScrArea *sa, ARegion *ar)
return 0;
}
-static int panels_re_align(ScrArea *sa, ARegion *ar, Panel **r_pa)
+static bool panel_active_animation_changed(ListBase *lb, Panel **pa_animation, bool *no_animation)
{
- Panel *pa;
- int active = 0;
+ for (Panel *pa = lb->first; pa; pa = pa->next) {
+ /* Detect panel active flag changes. */
+ if (!(pa->type && pa->type->parent)) {
+ if ((pa->runtime_flag & PNL_WAS_ACTIVE) && !(pa->runtime_flag & PNL_ACTIVE)) {
+ return true;
+ }
+ if (!(pa->runtime_flag & PNL_WAS_ACTIVE) && (pa->runtime_flag & PNL_ACTIVE)) {
+ return true;
+ }
+ }
+
+ if ((pa->runtime_flag & PNL_ACTIVE) && !(pa->flag & PNL_CLOSED)) {
+ if (panel_active_animation_changed(&pa->children, pa_animation, no_animation)) {
+ return true;
+ }
+ }
+
+ /* Detect animation. */
+ if (pa->activedata) {
+ uiHandlePanelData *data = pa->activedata;
+ if (data->state == PANEL_STATE_ANIMATION) {
+ *pa_animation = pa;
+ }
+ else {
+ /* Don't animate while handling other interaction. */
+ *no_animation = true;
+ }
+ }
+ if ((pa->runtime_flag & PNL_ANIM_ALIGN) && !(*pa_animation)) {
+ *pa_animation = pa;
+ }
+ }
+
+ return false;
+}
- *r_pa = NULL;
+static bool panels_need_realign(ScrArea *sa, ARegion *ar, Panel **pa_animate)
+{
+ *pa_animate = NULL;
if (sa->spacetype == SPACE_BUTS && ar->regiontype == RGN_TYPE_WINDOW) {
SpaceButs *sbuts = sa->spacedata.first;
- if (sbuts->align)
- if (sbuts->re_align || sbuts->mainbo != sbuts->mainb)
- return 1;
+ if (sbuts->mainbo != sbuts->mainb) {
+ return true;
+ }
+ }
+ else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW) {
+ return true;
+ }
+ else if (sa->spacetype == SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS) {
+ return true;
}
- else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW)
- return 1;
- else if (sa->spacetype == SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS)
- return 1;
- /* in case panel is added or disappears */
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if ((pa->runtime_flag & PNL_WAS_ACTIVE) && !(pa->runtime_flag & PNL_ACTIVE))
- return 1;
- if (!(pa->runtime_flag & PNL_WAS_ACTIVE) && (pa->runtime_flag & PNL_ACTIVE))
- return 1;
- if (pa->activedata)
- active = 1;
+ /* Detect if a panel was added or removed. */
+ Panel *pa_animation = NULL;
+ bool no_animation = false;
+ if (panel_active_animation_changed(&ar->panels, &pa_animation, &no_animation)) {
+ return true;
}
- /* in case we need to do an animation (size changes) */
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if (pa->runtime_flag & PNL_ANIM_ALIGN) {
- if (!active)
- *r_pa = pa;
- return 1;
+ /* Detect panel marked for animation, if we're not already animating. */
+ if (pa_animation) {
+ if (!no_animation) {
+ *pa_animate = pa_animation;
}
+ return true;
}
- return 0;
+ return false;
}
/****************************** panels ******************************/
@@ -216,14 +255,14 @@ static void ui_panel_copy_offset(Panel *pa, Panel *papar)
*/
/* #define UI_USE_PANELTAB */
-Panel *UI_panel_find_by_type(ARegion *ar, PanelType *pt)
+Panel *UI_panel_find_by_type(ListBase *lb, PanelType *pt)
{
Panel *pa;
const char *idname = pt->idname;
#ifdef UI_USE_PANELTAB
const char *tabname = pt->idname;
- for (pa = ar->panels.first; pa; pa = pa->next) {
+ for (pa = lb->first; pa; pa = pa->next) {
if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) {
if (STREQLEN(pa->tabname, tabname, sizeof(pa->tabname))) {
return pa;
@@ -231,7 +270,7 @@ Panel *UI_panel_find_by_type(ARegion *ar, PanelType *pt)
}
}
#else
- for (pa = ar->panels.first; pa; pa = pa->next) {
+ for (pa = lb->first; pa; pa = pa->next) {
if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) {
return pa;
}
@@ -244,7 +283,7 @@ Panel *UI_panel_find_by_type(ARegion *ar, PanelType *pt)
/**
* \note \a pa should be return value from #UI_panel_find_by_type and can be NULL.
*/
-Panel *UI_panel_begin(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, Panel *pa, bool *r_open)
+Panel *UI_panel_begin(ScrArea *sa, ARegion *ar, ListBase *lb, uiBlock *block, PanelType *pt, Panel *pa, bool *r_open)
{
Panel *palast, *panext;
const char *drawname = CTX_IFACE_(pt->translation_context, pt->label);
@@ -276,9 +315,11 @@ Panel *UI_panel_begin(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, P
pa->ofsy = 0;
pa->sizex = 0;
pa->sizey = 0;
+ pa->blocksizex = 0;
+ pa->blocksizey = 0;
pa->runtime_flag |= PNL_NEW_ADDED;
- BLI_addtail(&ar->panels, pa);
+ BLI_addtail(lb, pa);
#ifdef UI_USE_PANELTAB
BLI_strncpy(pa->tabname, tabname, sizeof(pa->tabname));
@@ -286,7 +327,7 @@ Panel *UI_panel_begin(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, P
/* make new Panel tabbed? */
if (hookname) {
Panel *patab;
- for (patab = ar->panels.first; patab; patab = patab->next) {
+ for (patab = lb->first; patab; patab = patab->next) {
if ((patab->runtime_flag & PNL_ACTIVE) && patab->paneltab == NULL) {
if (STREQLEN(hookname, patab->panelname, sizeof(patab->panelname))) {
if (STREQLEN(tabname, patab->tabname, sizeof(patab->tabname))) {
@@ -309,6 +350,8 @@ Panel *UI_panel_begin(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, P
/* Force update of panels' positions! */
pa->sizex = 0;
pa->sizey = 0;
+ pa->blocksizex = 0;
+ pa->blocksizey = 0;
}
BLI_strncpy(pa->drawname, drawname, sizeof(pa->drawname));
@@ -316,14 +359,18 @@ Panel *UI_panel_begin(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, P
/* if a new panel is added, we insert it right after the panel
* that was last added. this way new panels are inserted in the
* right place between versions */
- for (palast = ar->panels.first; palast; palast = palast->next)
- if (palast->runtime_flag & PNL_LAST_ADDED)
+ for (palast = lb->first; palast; palast = palast->next) {
+ if (palast->runtime_flag & PNL_LAST_ADDED) {
+ BLI_remlink(lb, pa);
+ BLI_insertlinkafter(lb, palast, pa);
break;
+ }
+ }
if (newpanel) {
pa->sortorder = (palast) ? palast->sortorder + 1 : 0;
- for (panext = ar->panels.first; panext; panext = panext->next)
+ for (panext = lb->first; panext; panext = panext->next)
if (panext != pa && panext->sortorder >= pa->sortorder)
panext->sortorder++;
}
@@ -349,6 +396,19 @@ void UI_panel_end(uiBlock *block, int width, int height)
{
Panel *pa = block->panel;
+ /* Set panel size excluding children. */
+ pa->blocksizex = width;
+ pa->blocksizey = height;
+
+ /* Compute total panel size including children. */
+ for (Panel *pachild = pa->children.first; pachild; pachild = pachild->next) {
+ if (pachild->runtime_flag & PNL_ACTIVE) {
+ width = max_ii(width, pachild->sizex);
+ height += get_panel_real_size_y(pachild);
+ }
+ }
+
+ /* Update total panel size. */
if (pa->runtime_flag & PNL_NEW_ADDED) {
pa->runtime_flag &= ~PNL_NEW_ADDED;
pa->sizex = width;
@@ -373,15 +433,13 @@ void UI_panel_end(uiBlock *block, int width, int height)
static void ui_offset_panel_block(uiBlock *block)
{
uiStyle *style = UI_style_get_dpi();
- uiBut *but;
- int ofsy;
/* compute bounds and offset */
ui_block_bounds_calc(block);
- ofsy = block->panel->sizey - style->panelspace;
+ int ofsy = block->panel->sizey - style->panelspace;
- for (but = block->buttons.first; but; but = but->next) {
+ for (uiBut *but = block->buttons.first; but; but = but->next) {
but->rect.ymin += ofsy;
but->rect.ymax += ofsy;
}
@@ -393,81 +451,59 @@ static void ui_offset_panel_block(uiBlock *block)
/**************************** drawing *******************************/
-/* extern used by previewrender */
-#if 0 /*UNUSED 2.5*/
-static void uiPanelPush(uiBlock *block)
-{
- glPushMatrix();
-
- if (block->panel)
- glTranslatef((float)block->panel->ofsx, (float)block->panel->ofsy, 0.0);
-}
-
-static void uiPanelPop(uiBlock *UNUSED(block))
-{
- glPopMatrix();
-}
-#endif
-
/* triangle 'icon' for panel header */
-void UI_draw_icon_tri(float x, float y, char dir)
+void UI_draw_icon_tri(float x, float y, char dir, const float color[4])
{
float f3 = 0.15 * U.widget_unit;
float f5 = 0.25 * U.widget_unit;
float f7 = 0.35 * U.widget_unit;
if (dir == 'h') {
- ui_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y);
+ UI_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y, color);
}
else if (dir == 't') {
- ui_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3);
+ UI_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3, color);
}
else { /* 'v' = vertical, down */
- ui_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7);
- }
-}
-
-/* triangle 'icon' inside rect */
-static void ui_draw_tria_rect(const rctf *rect, char dir)
-{
- if (dir == 'h') {
- float half = 0.5f * BLI_rctf_size_y(rect);
- ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half);
- }
- else {
- float half = 0.5f * BLI_rctf_size_x(rect);
- ui_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin);
+ UI_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7, color);
}
}
-static void ui_draw_anti_x(float x1, float y1, float x2, float y2)
+static void ui_draw_anti_x(unsigned int pos, float x1, float y1, float x2, float y2)
{
/* set antialias line */
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
+ GPU_line_smooth(true);
+ GPU_blend(true);
+
+ GPU_line_width(2.0);
+
+ immBegin(GWN_PRIM_LINES, 4);
- glLineWidth(2.0);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
- fdrawline(x1, y1, x2, y2);
- fdrawline(x1, y2, x2, y1);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y1);
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ immEnd();
+
+ GPU_line_smooth(false);
+ GPU_blend(false);
}
/* x 'icon' for panel header */
-static void ui_draw_x_icon(float x, float y)
+static void ui_draw_x_icon(unsigned int pos, float x, float y)
{
- ui_draw_anti_x(x, y, x + 9.375f, y + 9.375f);
+ ui_draw_anti_x(pos, x, y, x + 9.375f, y + 9.375f);
}
#define PNL_ICON UI_UNIT_X /* could be UI_UNIT_Y too */
-static void ui_draw_panel_scalewidget(const rcti *rect)
+static void ui_draw_panel_scalewidget(unsigned int pos, const rcti *rect)
{
float xmin, xmax, dx;
float ymin, ymax, dy;
@@ -480,19 +516,56 @@ static void ui_draw_panel_scalewidget(const rcti *rect)
dx = 0.5f * (xmax - xmin);
dy = 0.5f * (ymax - ymin);
- glEnable(GL_BLEND);
- glColor4ub(255, 255, 255, 50);
- fdrawline(xmin, ymin, xmax, ymax);
- fdrawline(xmin + dx, ymin, xmax, ymax - dy);
+ GPU_blend(true);
+ immUniformColor4ub(255, 255, 255, 50);
+
+ immBegin(GWN_PRIM_LINES, 4);
+
+ immVertex2f(pos, xmin, ymin);
+ immVertex2f(pos, xmax, ymax);
+
+ immVertex2f(pos, xmin + dx, ymin);
+ immVertex2f(pos, xmax, ymax - dy);
+
+ immEnd();
+
+ immUniformColor4ub(0, 0, 0, 50);
+
+ immBegin(GWN_PRIM_LINES, 4);
+
+ immVertex2f(pos, xmin, ymin + 1);
+ immVertex2f(pos, xmax, ymax + 1);
- glColor4ub(0, 0, 0, 50);
- fdrawline(xmin, ymin + 1, xmax, ymax + 1);
- fdrawline(xmin + dx, ymin + 1, xmax, ymax - dy + 1);
- glDisable(GL_BLEND);
+ immVertex2f(pos, xmin + dx, ymin + 1);
+ immVertex2f(pos, xmax, ymax - dy + 1);
+
+ immEnd();
+
+ GPU_blend(false);
+}
+
+static void immRectf_tris_color_ex(
+ unsigned int pos, float x1, float y1, float x2, float y2,
+ unsigned int col, const float color[3])
+{
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x1, y1);
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x2, y1);
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x2, y2);
+
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x1, y1);
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x2, y2);
+ immAttrib4fv(col, color);
+ immVertex2f(pos, x1, y2);
}
-static void ui_draw_panel_dragwidget(const rctf *rect)
+
+static void ui_draw_panel_dragwidget(unsigned int pos, unsigned int col, const rctf *rect)
{
- unsigned char col_back[3], col_high[3], col_dark[3];
+ float col_high[4], col_dark[4];
const int col_tint = 84;
const int px = (int)U.pixelsize;
@@ -507,26 +580,41 @@ static void ui_draw_panel_dragwidget(const rctf *rect)
const int x_ofs = y_ofs;
int i_x, i_y;
-
- UI_GetThemeColor3ubv(UI_GetThemeValue(TH_PANEL_SHOW_HEADER) ? TH_PANEL_HEADER : TH_PANEL_BACK, col_back);
- UI_GetColorPtrShade3ubv(col_back, col_high, col_tint);
- UI_GetColorPtrShade3ubv(col_back, col_dark, -col_tint);
-
+ UI_GetThemeColorShade4fv(TH_PANEL_HEADER, col_tint, col_high);
+ UI_GetThemeColorShade4fv(TH_PANEL_BACK, -col_tint, col_dark);
/* draw multiple boxes */
+ immBegin(GWN_PRIM_TRIS, 4 * 2 * (6 * 2));
for (i_x = 0; i_x < 4; i_x++) {
for (i_y = 0; i_y < 2; i_y++) {
const int x_co = (x_min + x_ofs) + (i_x * (box_size + box_margin));
const int y_co = (y_min + y_ofs) + (i_y * (box_size + box_margin));
- glColor3ubv(col_dark);
- glRectf(x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom);
- glColor3ubv(col_high);
- glRectf(x_co - box_size, y_co, x_co, y_co + box_size);
+ immRectf_tris_color_ex(
+ pos, x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom,
+ col, col_dark);
+ immRectf_tris_color_ex(
+ pos, x_co - box_size, y_co, x_co, y_co + box_size,
+ col, col_high);
}
}
+ immEnd();
}
+/* For button layout next to label. */
+void UI_panel_label_offset(uiBlock *block, int *x, int *y)
+{
+ Panel *panel = block->panel;
+ uiStyle *style = UI_style_get_dpi();
+ const bool is_subpanel = (panel->type && panel->type->parent);
+
+ *x = UI_UNIT_X * 1.1f;
+ *y = (UI_UNIT_Y * 1.1f) + style->panelspace;
+
+ if (is_subpanel) {
+ *x += 5.0f / block->aspect;
+ }
+}
static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const rcti *rect, char dir)
{
@@ -534,6 +622,9 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const r
rcti hrect;
int pnl_icons;
const char *activename = panel->drawname[0] ? panel->drawname : panel->panelname;
+ const bool is_subpanel = (panel->type && panel->type->parent);
+ uiFontStyle *fontstyle = (is_subpanel) ? &style->widgetlabel : &style->paneltitle;
+ unsigned char col_title[4];
/* + 0.001f to avoid flirting with float inaccuracy */
if (panel->control & UI_PNL_CLOSE)
@@ -541,22 +632,22 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const r
else
pnl_icons = (panel->labelofs + PNL_ICON + 5) / block->aspect + 0.001f;
- /* active tab */
/* draw text label */
- UI_ThemeColor(TH_TITLE);
+ UI_GetThemeColor3ubv(TH_TITLE, col_title);
+ col_title[3] = 255;
hrect = *rect;
if (dir == 'h') {
hrect.xmin = rect->xmin + pnl_icons;
hrect.ymin += 2.0f / block->aspect;
- UI_fontstyle_draw(&style->paneltitle, &hrect, activename);
+ UI_fontstyle_draw(fontstyle, &hrect, activename, col_title);
}
else {
/* ignore 'pnl_icons', otherwise the text gets offset horizontally
* + 0.001f to avoid flirting with float inaccuracy
*/
hrect.xmin = rect->xmin + (PNL_ICON + 5) / block->aspect + 0.001f;
- UI_fontstyle_draw_rotated(&style->paneltitle, &hrect, activename);
+ UI_fontstyle_draw_rotated(fontstyle, &hrect, activename, col_title);
}
}
@@ -566,9 +657,11 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
Panel *panel = block->panel;
rcti headrect;
rctf itemrect;
- int ofsx;
+ float color[4];
const bool is_closed_x = (panel->flag & PNL_CLOSEDX) ? true : false;
const bool is_closed_y = (panel->flag & PNL_CLOSEDY) ? true : false;
+ const bool is_subpanel = (panel->type && panel->type->parent);
+ const bool show_drag = !is_subpanel;
if (panel->paneltab) return;
if (panel->type && (panel->type->flag & PNL_NO_HEADER)) return;
@@ -579,38 +672,40 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
headrect.ymin = headrect.ymax;
headrect.ymax = headrect.ymin + floor(PNL_HEADER / block->aspect + 0.001f);
- {
+ rcti titlerect = headrect;
+ if (is_subpanel) {
+ titlerect.xmin += 5.0f / block->aspect;
+ }
+
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ if (!is_subpanel) {
float minx = rect->xmin;
float maxx = is_closed_x ? (minx + PNL_HEADER / block->aspect) : rect->xmax;
float y = headrect.ymax;
- glEnable(GL_BLEND);
+ GPU_blend(true);
- if (UI_GetThemeValue(TH_PANEL_SHOW_HEADER)) {
- /* draw with background color */
- UI_ThemeColor4(TH_PANEL_HEADER);
- glRectf(minx, headrect.ymin + 1, maxx, y);
+ /* draw with background color */
+ immUniformThemeColor(TH_PANEL_HEADER);
+ immRectf(pos, minx, headrect.ymin, maxx, y);
- fdrawline(minx, y, maxx, y);
- fdrawline(minx, y, maxx, y);
- }
- else if (!(panel->runtime_flag & PNL_FIRST)) {
- /* draw embossed separator */
+ immBegin(GWN_PRIM_LINES, 4);
- if (is_closed_x == false) {
- minx += 5.0f / block->aspect;
- maxx -= 5.0f / block->aspect;
- }
+ immVertex2f(pos, minx, y);
+ immVertex2f(pos, maxx, y);
- glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
- fdrawline(minx, y, maxx, y);
- glColor4f(1.0f, 1.0f, 1.0f, 0.25f);
- fdrawline(minx, y - 1, maxx, y - 1);
- }
+ immVertex2f(pos, minx, y);
+ immVertex2f(pos, maxx, y);
+
+ immEnd();
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
+ immUnbindProgram();
+
/* draw optional pin icon */
#ifdef USE_PIN_HIDDEN
@@ -619,26 +714,39 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
if (show_pin)
#endif
{
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw_aspect(
headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect), headrect.ymin + (5.0f / block->aspect),
(panel->flag & PNL_PIN) ? ICON_PINNED : ICON_UNPINNED,
(block->aspect / UI_DPI_FAC), 1.0f);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
+
/* horizontal title */
if (is_closed_x == false) {
- ui_draw_aligned_panel_header(style, block, &headrect, 'h');
-
- /* itemrect smaller */
- itemrect.xmax = headrect.xmax - 5.0f / block->aspect;
- itemrect.xmin = itemrect.xmax - BLI_rcti_size_y(&headrect);
- itemrect.ymin = headrect.ymin;
- itemrect.ymax = headrect.ymax;
-
- BLI_rctf_scale(&itemrect, 0.7f);
- ui_draw_panel_dragwidget(&itemrect);
+ ui_draw_aligned_panel_header(style, block, &titlerect, 'h');
+
+ if (show_drag) {
+ uint col;
+ Gwn_VertFormat *format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+
+ /* itemrect smaller */
+ itemrect.xmax = headrect.xmax - 5.0f / block->aspect;
+ itemrect.xmin = itemrect.xmax - BLI_rcti_size_y(&headrect);
+ itemrect.ymin = headrect.ymin;
+ itemrect.ymax = headrect.ymax;
+
+ BLI_rctf_scale(&itemrect, 0.7f);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ ui_draw_panel_dragwidget(pos, col, &itemrect);
+ immUnbindProgram();
+
+ /* Restore format for the following draws. */
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
}
/* if the panel is minimized vertically:
@@ -650,6 +758,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
else if (is_closed_x) {
/* draw vertical title */
ui_draw_aligned_panel_header(style, block, &headrect, 'v');
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
}
/* an open panel */
else {
@@ -658,55 +767,63 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
if (panel->control & UI_PNL_SOLID) UI_draw_roundbox_corner_set(UI_CNR_ALL);
else UI_draw_roundbox_corner_set(UI_CNR_NONE);
- UI_ThemeColorShade(TH_BACK, -120);
- UI_draw_roundbox_unfilled(0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8);
+ UI_GetThemeColorShade4fv(TH_BACK, -120, color);
+ UI_draw_roundbox_aa(false, 0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8, color);
}
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ GPU_blend(true);
+
/* panel backdrop */
- if (UI_GetThemeValue(TH_PANEL_SHOW_BACK)) {
- /* draw with background color */
- glEnable(GL_BLEND);
- UI_ThemeColor4(TH_PANEL_BACK);
- glRecti(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- }
+ int panel_col = is_subpanel ? TH_PANEL_SUB_BACK : TH_PANEL_BACK;
+
+ immUniformThemeColor(panel_col);
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
if (panel->control & UI_PNL_SCALE)
- ui_draw_panel_scalewidget(rect);
+ ui_draw_panel_scalewidget(pos, rect);
+
+ immUnbindProgram();
}
/* draw optional close icon */
- ofsx = 6;
if (panel->control & UI_PNL_CLOSE) {
- UI_ThemeColor(TH_TITLE);
- ui_draw_x_icon(rect->xmin + 2 + ofsx, rect->ymax + 2);
- ofsx = 22;
+ const int ofsx = 6;
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor3(TH_TITLE);
+ ui_draw_x_icon(pos, rect->xmin + 2 + ofsx, rect->ymax + 2);
+ immUnbindProgram();
}
/* draw collapse icon */
- UI_ThemeColor(TH_TITLE);
/* itemrect smaller */
- itemrect.xmin = headrect.xmin + 5.0f / block->aspect;
- itemrect.xmax = itemrect.xmin + BLI_rcti_size_y(&headrect);
- itemrect.ymin = headrect.ymin;
- itemrect.ymax = headrect.ymax;
-
- BLI_rctf_scale(&itemrect, 0.35f);
+ itemrect.xmin = titlerect.xmin + 3.0f / block->aspect;
+ itemrect.xmax = itemrect.xmin + BLI_rcti_size_y(&titlerect);
+ itemrect.ymin = titlerect.ymin;
+ itemrect.ymax = titlerect.ymax;
- if (is_closed_y)
- ui_draw_tria_rect(&itemrect, 'h');
- else if (is_closed_x)
- ui_draw_tria_rect(&itemrect, 'h');
- else
- ui_draw_tria_rect(&itemrect, 'v');
+ BLI_rctf_scale(&itemrect, 0.25f);
- (void)ofsx;
+ {
+ float tria_color[4];
+ UI_GetThemeColor3fv(TH_TITLE, tria_color);
+ tria_color[3] = 1.0f;
+
+ if (is_closed_y)
+ ui_draw_anti_tria_rect(&itemrect, 'h', tria_color);
+ else if (is_closed_x)
+ ui_draw_anti_tria_rect(&itemrect, 'h', tria_color);
+ else
+ ui_draw_anti_tria_rect(&itemrect, 'v', tria_color);
+ }
}
/************************** panel alignment *************************/
-static int get_panel_header(Panel *pa)
+static int get_panel_header(const Panel *pa)
{
if (pa->type && (pa->type->flag & PNL_NO_HEADER))
return 0;
@@ -714,7 +831,7 @@ static int get_panel_header(Panel *pa)
return PNL_HEADER;
}
-static int get_panel_size_y(Panel *pa)
+static int get_panel_size_y(const Panel *pa)
{
if (pa->type && (pa->type->flag & PNL_NO_HEADER))
return pa->sizey;
@@ -722,6 +839,21 @@ static int get_panel_size_y(Panel *pa)
return PNL_HEADER + pa->sizey;
}
+static int get_panel_real_size_y(const Panel *pa)
+{
+ int sizey = (pa->flag & PNL_CLOSED) ? 0 : pa->sizey;
+
+ if (pa->type && (pa->type->flag & PNL_NO_HEADER))
+ return sizey;
+
+ return PNL_HEADER + sizey;
+}
+
+int UI_panel_size_y(const Panel *pa)
+{
+ return get_panel_real_size_y(pa);
+}
+
/* this function is needed because uiBlock and Panel itself don't
* change sizey or location when closed */
static int get_panel_real_ofsy(Panel *pa)
@@ -794,6 +926,24 @@ static int compare_panel(const void *a1, const void *a2)
return 0;
}
+static void align_sub_panels(Panel *pa)
+{
+ /* Position sub panels. */
+ int ofsy = get_panel_real_ofsy(pa) + pa->sizey - pa->blocksizey;
+
+ for (Panel *pachild = pa->children.first; pachild; pachild = pachild->next) {
+ if (pachild->runtime_flag & PNL_ACTIVE) {
+ pachild->ofsx = pa->ofsx;
+ pachild->ofsy = ofsy - get_panel_size_y(pachild);
+ ofsy -= get_panel_real_size_y(pachild);
+
+ if (pachild->children.first) {
+ align_sub_panels(pachild);
+ }
+ }
+ }
+}
+
/* this doesnt draw */
/* returns 1 when it did something */
static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bool drag)
@@ -885,10 +1035,17 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
}
}
- /* copy locations to tabs */
- for (pa = ar->panels.first; pa; pa = pa->next)
- if (pa->paneltab && (pa->runtime_flag & PNL_ACTIVE))
- ui_panel_copy_offset(pa, pa->paneltab);
+ /* set locations for tabbed and sub panels */
+ for (pa = ar->panels.first; pa; pa = pa->next) {
+ if (pa->runtime_flag & PNL_ACTIVE) {
+ if (pa->paneltab) {
+ ui_panel_copy_offset(pa, pa->paneltab);
+ }
+ if (pa->children.first) {
+ align_sub_panels(pa);
+ }
+ }
+ }
/* free panelsort array */
for (ps = panelsort, a = 0; a < tot; a++, ps++) {
@@ -958,20 +1115,27 @@ static void ui_do_animate(const bContext *C, Panel *panel)
}
}
-void UI_panels_begin(const bContext *UNUSED(C), ARegion *ar)
+static void panel_list_clear_active(ListBase *lb)
{
- Panel *pa;
-
/* set all panels as inactive, so that at the end we know
* which ones were used */
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if (pa->runtime_flag & PNL_ACTIVE)
+ for (Panel *pa = lb->first; pa; pa = pa->next) {
+ if (pa->runtime_flag & PNL_ACTIVE) {
pa->runtime_flag = PNL_WAS_ACTIVE;
- else
+ }
+ else {
pa->runtime_flag = 0;
+ }
+
+ panel_list_clear_active(&pa->children);
}
}
+void UI_panels_begin(const bContext *UNUSED(C), ARegion *ar)
+{
+ panel_list_clear_active(&ar->panels);
+}
+
/* only draws blocks with panels */
void UI_panels_end(const bContext *C, ARegion *ar, int *x, int *y)
{
@@ -1010,8 +1174,7 @@ void UI_panels_end(const bContext *C, ARegion *ar, int *x, int *y)
}
/* re-align, possibly with animation */
- if (panels_re_align(sa, ar, &pa)) {
- /* XXX code never gets here... PNL_ANIM_ALIGN flag is never set */
+ if (panels_need_realign(sa, ar, &pa)) {
if (pa)
panel_activate_state(C, pa, PANEL_STATE_ANIMATION);
else
@@ -1038,14 +1201,16 @@ void UI_panels_draw(const bContext *C, ARegion *ar)
UI_ThemeClearColor(TH_BACK);
- /* draw panels, selected on top */
- for (block = ar->uiblocks.first; block; block = block->next) {
+ /* Draw panels, selected on top. Also in reverse order, because
+ * UI blocks are added in reverse order and we need child panels
+ * to draw on top. */
+ for (block = ar->uiblocks.last; block; block = block->prev) {
if (block->active && block->panel && !(block->panel->flag & PNL_SELECT)) {
UI_block_draw(C, block);
}
}
- for (block = ar->uiblocks.first; block; block = block->next) {
+ for (block = ar->uiblocks.last; block; block = block->prev) {
if (block->active && block->panel && (block->panel->flag & PNL_SELECT)) {
UI_block_draw(C, block);
}
@@ -1307,6 +1472,8 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
#else
const bool show_pin = UI_panel_category_is_visible(ar);
#endif
+ const bool is_subpanel = (block->panel->type && block->panel->type->parent);
+ const bool show_drag = !is_subpanel;
int align = panel_aligned(sa, ar), button = 0;
@@ -1401,7 +1568,11 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
else
ED_region_tag_redraw(ar);
}
- else if (BLI_rctf_isect_x(&rect_drag, mx)) {
+ else if (show_drag && BLI_rctf_isect_x(&rect_drag, mx)) {
+ /* XXX, for now don't allow dragging in floating windows yet. */
+ if (ar->alignment == RGN_ALIGN_FLOAT) {
+ return;
+ }
panel_activate_state(C, block->panel, PANEL_STATE_DRAG);
}
else if (show_pin && BLI_rctf_isect_x(&rect_pin, mx)) {
@@ -1514,12 +1685,13 @@ void UI_panel_category_clear_all(ARegion *ar)
BLI_freelistN(&ar->panels_category);
}
-/* based on UI_draw_roundbox_gl_mode, check on making a version which allows us to skip some sides */
+/* based on UI_draw_roundbox, check on making a version which allows us to skip some sides */
static void ui_panel_category_draw_tab(
- int mode, float minx, float miny, float maxx, float maxy, float rad,
+ bool filled, float minx, float miny, float maxx, float maxy, float rad,
int roundboxtype,
- const bool use_highlight, const bool use_shadow,
- const unsigned char highlight_fade[3])
+ bool use_highlight, bool use_shadow,
+ const unsigned char highlight_fade[3],
+ const unsigned char col[3])
{
float vec[4][2] = {
{0.195, 0.02},
@@ -1528,74 +1700,113 @@ static void ui_panel_category_draw_tab(
{0.98, 0.805}};
int a;
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
/* mult */
for (a = 0; a < 4; a++) {
mul_v2_fl(vec[a], rad);
}
- glBegin(mode);
+ uint vert_len = 0;
+ if (use_highlight) {
+ vert_len += (roundboxtype & UI_CNR_TOP_RIGHT) ? 6 : 1;
+ vert_len += (roundboxtype & UI_CNR_TOP_LEFT) ? 6 : 1;
+ }
+ if (use_highlight && !use_shadow) {
+ vert_len++;
+ }
+ else {
+ vert_len += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 6 : 1;
+ vert_len += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 6 : 1;
+ }
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_STRIP, vert_len);
/* start with corner right-top */
if (use_highlight) {
if (roundboxtype & UI_CNR_TOP_RIGHT) {
- glVertex2f(maxx, maxy - rad);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, maxx, maxy - rad);
for (a = 0; a < 4; a++) {
- glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
}
- glVertex2f(maxx - rad, maxy);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, maxx - rad, maxy);
}
else {
- glVertex2f(maxx, maxy);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, maxx, maxy);
}
/* corner left-top */
if (roundboxtype & UI_CNR_TOP_LEFT) {
- glVertex2f(minx + rad, maxy);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, minx + rad, maxy);
for (a = 0; a < 4; a++) {
- glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
}
- glVertex2f(minx, maxy - rad);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, minx, maxy - rad);
}
else {
- glVertex2f(minx, maxy);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, minx, maxy);
}
}
if (use_highlight && !use_shadow) {
if (highlight_fade) {
- glColor3ubv(highlight_fade);
+ immAttrib3ubv(color, highlight_fade);
+ }
+ else {
+ immAttrib3ubv(color, col);
}
- glVertex2f(minx, miny + rad);
- glEnd();
+ immVertex2f(pos, minx, miny + rad);
+ immEnd();
+ immUnbindProgram();
return;
}
/* corner left-bottom */
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
- glVertex2f(minx, miny + rad);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, minx, miny + rad);
for (a = 0; a < 4; a++) {
- glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
}
- glVertex2f(minx + rad, miny);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, minx + rad, miny);
}
else {
- glVertex2f(minx, miny);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, minx, miny);
}
/* corner right-bottom */
-
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
- glVertex2f(maxx - rad, miny);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, maxx - rad, miny);
for (a = 0; a < 4; a++) {
- glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
}
- glVertex2f(maxx, miny + rad);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, maxx, miny + rad);
}
else {
- glVertex2f(maxx, miny);
+ immAttrib3ubv(color, col);
+ immVertex2f(pos, maxx, miny);
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
@@ -1716,23 +1927,28 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* begin drawing */
- glEnable(GL_LINE_SMOOTH);
+ GPU_line_smooth(true);
+
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* draw the background */
if (is_alpha) {
- glEnable(GL_BLEND);
- glColor4ubv(theme_col_tab_bg);
+ GPU_blend(true);
+ immUniformColor4ubv(theme_col_tab_bg);
}
else {
- glColor3ubv(theme_col_tab_bg);
+ immUniformColor3ubv(theme_col_tab_bg);
}
- glRecti(v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax);
+ immRecti(pos, v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax);
if (is_alpha) {
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
+ immUnbindProgram();
+
for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
const rcti *rct = &pc_dyn->rect;
const char *category_id = pc_dyn->idname;
@@ -1749,37 +1965,42 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
}
#endif
- glEnable(GL_BLEND);
+ GPU_blend(true);
#ifdef USE_FLAT_INACTIVE
if (is_active)
#endif
{
- glColor3ubv(is_active ? theme_col_tab_active : theme_col_tab_inactive);
ui_panel_category_draw_tab(
- GL_POLYGON, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
- tab_curve_radius - px, roundboxtype, true, true, NULL);
+ true, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
+ tab_curve_radius - px, roundboxtype, true, true, NULL,
+ is_active ? theme_col_tab_active : theme_col_tab_inactive);
/* tab outline */
- glColor3ubv(theme_col_tab_outline);
ui_panel_category_draw_tab(
- GL_LINE_STRIP, rct->xmin - px, rct->ymin - px, rct->xmax - px, rct->ymax + px,
- tab_curve_radius, roundboxtype, true, true, NULL);
+ false, rct->xmin - px, rct->ymin - px, rct->xmax - px, rct->ymax + px,
+ tab_curve_radius, roundboxtype, true, true, NULL, theme_col_tab_outline);
+
/* tab highlight (3d look) */
- glColor3ubv(is_active ? theme_col_tab_highlight : theme_col_tab_highlight_inactive);
ui_panel_category_draw_tab(
- GL_LINE_STRIP, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
+ false, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
tab_curve_radius, roundboxtype, true, false,
- is_active ? theme_col_back : theme_col_tab_inactive);
+ is_active ? theme_col_back : theme_col_tab_inactive,
+ is_active ? theme_col_tab_highlight : theme_col_tab_highlight_inactive);
}
/* tab blackline */
if (!is_active) {
- glColor3ubv(theme_col_tab_divider);
- glRecti(v2d->mask.xmin + category_tabs_width - px,
- rct->ymin - tab_v_pad,
- v2d->mask.xmin + category_tabs_width,
- rct->ymax + tab_v_pad);
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, v2d->mask.xmin + category_tabs_width - px,
+ rct->ymin - tab_v_pad,
+ v2d->mask.xmin + category_tabs_width,
+ rct->ymax + tab_v_pad);
+
+ immUnbindProgram();
}
if (do_scaletabs) {
@@ -1793,47 +2014,50 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* tab titles */
/* draw white shadow to give text more depth */
- glColor3ubv(theme_col_text);
+ BLF_color3ubv(fontid, theme_col_text);
/* main tab title */
BLF_draw(fontid, category_id_draw, category_draw_len);
- glDisable(GL_BLEND);
+ GPU_blend(false);
/* tab blackline remaining (last tab) */
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
if (pc_dyn->prev == NULL) {
- glColor3ubv(theme_col_tab_divider);
- glRecti(v2d->mask.xmin + category_tabs_width - px,
- rct->ymax + px,
- v2d->mask.xmin + category_tabs_width,
- v2d->mask.ymax);
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, v2d->mask.xmin + category_tabs_width - px,
+ rct->ymax + px,
+ v2d->mask.xmin + category_tabs_width,
+ v2d->mask.ymax);
}
if (pc_dyn->next == NULL) {
- glColor3ubv(theme_col_tab_divider);
- glRecti(v2d->mask.xmin + category_tabs_width - px,
- 0,
- v2d->mask.xmin + category_tabs_width,
- rct->ymin);
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, v2d->mask.xmin + category_tabs_width - px,
+ 0,
+ v2d->mask.xmin + category_tabs_width,
+ rct->ymin);
}
#ifdef USE_FLAT_INACTIVE
/* draw line between inactive tabs */
if (is_active == false && is_active_prev == false && pc_dyn->prev) {
- glColor3ubv(theme_col_tab_divider);
- glRecti(v2d->mask.xmin + (category_tabs_width / 5),
- rct->ymax + px,
- (v2d->mask.xmin + category_tabs_width) - (category_tabs_width / 5),
- rct->ymax + (px * 3));
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, v2d->mask.xmin + (category_tabs_width / 5),
+ rct->ymax + px,
+ (v2d->mask.xmin + category_tabs_width) - (category_tabs_width / 5),
+ rct->ymax + (px * 3));
}
is_active_prev = is_active;
#endif
+ immUnbindProgram();
/* not essential, but allows events to be handled right up until the region edge [#38171] */
pc_dyn->rect.xmin = v2d->mask.xmin;
}
- glDisable(GL_LINE_SMOOTH);
+ GPU_line_smooth(false);
BLF_disable(fontid, BLF_ROTATION);
@@ -1904,6 +2128,11 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons
retval = WM_UI_HANDLER_CONTINUE;
+ /* Scrollbars can overlap panels now, they have handling priority. */
+ if (UI_view2d_mouse_in_scrollers(ar, &ar->v2d, event->x, event->y)) {
+ return retval;
+ }
+
/* handle category tabs */
if (has_category_tabs) {
if (event->val == KM_PRESS) {
@@ -2153,3 +2382,15 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
ED_region_tag_redraw(ar);
}
+
+PanelType *UI_paneltype_find(int space_id, int region_id, const char *idname)
+{
+ SpaceType *st = BKE_spacetype_from_id(space_id);
+ if (st) {
+ ARegionType *art = BKE_regiontype_from_id(st, region_id);
+ if (art) {
+ return BLI_findstring(&art->paneltypes, idname, offsetof(PanelType, idname));
+ }
+ }
+ return NULL;
+}
diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c
index f7dbb9b14ed..66f63fef82d 100644
--- a/source/blender/editors/interface/interface_query.c
+++ b/source/blender/editors/interface/interface_query.c
@@ -32,6 +32,9 @@
#include "interface_intern.h"
+#include "WM_api.h"
+#include "WM_types.h"
+
/* -------------------------------------------------------------------- */
/** \name Button (uiBut)
* \{ */
@@ -68,6 +71,31 @@ bool ui_but_is_toggle(const uiBut *but)
);
}
+#ifdef USE_UI_POPOVER_ONCE
+bool ui_but_is_popover_once_compat(const uiBut *but)
+{
+ return (
+ (but->type == UI_BTYPE_BUT) ||
+ ui_but_is_toggle(but)
+ );
+}
+#endif
+
+bool UI_but_is_tool(const uiBut *but)
+{
+ /* very evil! */
+ if (but->optype != NULL) {
+ static wmOperatorType *ot = NULL;
+ if (ot == NULL) {
+ ot = WM_operatortype_find("WM_OT_tool_set_by_name", false);
+ }
+ if (but->optype == ot) {
+ return true;
+ }
+ }
+ return false;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c
new file mode 100644
index 00000000000..f3ff6fdf2c0
--- /dev/null
+++ b/source/blender/editors/interface/interface_region_hud.c
@@ -0,0 +1,339 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/interface/interface_region_hud.c
+ * \ingroup edinterface
+ *
+ * Floating Persistent Region
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_userdef_types.h"
+
+#include "BLI_string.h"
+#include "BLI_rect.h"
+#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_main.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+
+#include "BIF_gl.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "BLT_translation.h"
+
+#include "ED_screen.h"
+#include "ED_undo.h"
+
+#include "interface_intern.h"
+#include "GPU_framebuffer.h"
+
+
+/* -------------------------------------------------------------------- */
+/** \name Utilities
+ * \{ */
+
+static bool last_redo_poll(const bContext *C)
+{
+ wmOperator *op = WM_operator_last_redo(C);
+ if (op == NULL) {
+ return false;
+ }
+ bool success = false;
+ if (WM_operator_repeat_check(C, op) &&
+ WM_operator_check_ui_empty(op->type) == false)
+ {
+ success = WM_operator_poll((bContext *)C, op->type);
+ }
+ return success;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Redo Panel
+ * \{ */
+
+static bool hud_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt))
+{
+ return last_redo_poll(C);
+}
+
+static void hud_panel_operator_redo_draw_header(const bContext *C, Panel *pa)
+{
+ wmOperator *op = WM_operator_last_redo(C);
+ BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname));
+}
+
+static void hud_panel_operator_redo_draw(const bContext *C, Panel *pa)
+{
+ wmOperator *op = WM_operator_last_redo(C);
+ if (op == NULL) {
+ return;
+ }
+ if (!WM_operator_check_ui_enabled(C, op->type->name)) {
+ uiLayoutSetEnabled(pa->layout, false);
+ }
+ uiLayout *col = uiLayoutColumn(pa->layout, false);
+ uiTemplateOperatorRedoProperties(col, C);
+}
+
+static void hud_panels_register(ARegionType *art, int space_type, int region_type)
+{
+ PanelType *pt;
+
+ pt = MEM_callocN(sizeof(PanelType), __func__);
+ strcpy(pt->idname, "OPERATOR_PT_redo");
+ strcpy(pt->label, N_("Redo"));
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw_header = hud_panel_operator_redo_draw_header;
+ pt->draw = hud_panel_operator_redo_draw;
+ pt->poll = hud_panel_operator_redo_poll;
+ pt->space_type = space_type;
+ pt->region_type = region_type;
+ BLI_addtail(&art->paneltypes, pt);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for Floating Region
+ * \{ */
+
+struct HudRegionData {
+ short regionid;
+};
+
+static void hud_region_init(wmWindowManager *wm, ARegion *ar)
+{
+ ED_region_panels_init(wm, ar);
+ UI_region_handlers_add(&ar->handlers);
+ ar->flag |= RGN_FLAG_TEMP_REGIONDATA;
+}
+
+static void hud_region_free(ARegion *ar)
+{
+ MEM_SAFE_FREE(ar->regiondata);
+}
+
+static void hud_region_layout(const bContext *C, ARegion *ar)
+{
+ bool ok = false;
+
+ {
+ struct HudRegionData *hrd = ar->regiondata;
+ if (hrd != NULL) {
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar_op = (hrd->regionid != -1) ? BKE_area_find_region_type(sa, hrd->regionid) : NULL;
+ ARegion *ar_prev = CTX_wm_region(C);
+ CTX_wm_region_set((bContext *)C, ar_op);
+ ok = last_redo_poll(C);
+ CTX_wm_region_set((bContext *)C, ar_prev);
+ }
+ }
+
+ if (!ok) {
+ ED_region_tag_redraw(ar);
+ ar->flag |= RGN_FLAG_HIDDEN;
+ return;
+ }
+
+ int size_y = ar->sizey;
+
+ ED_region_panels_layout(C, ar);
+
+ if (ar->panels.first && (ar->sizey != size_y)) {
+ View2D *v2d = &ar->v2d;
+ ar->winx = ar->sizex;
+ ar->winy = ar->sizey;
+
+ ar->winrct.xmax = (ar->winrct.xmin + ar->winx) - 1;
+ ar->winrct.ymax = (ar->winrct.ymin + ar->winy) - 1;
+
+ UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
+ }
+
+ /* restore view matrix */
+ UI_view2d_view_restore(C);
+}
+
+static void hud_region_draw(const bContext *C, ARegion *ar)
+{
+ UI_view2d_view_ortho(&ar->v2d);
+ wmOrtho2_region_pixelspace(ar);
+ GPU_clear_color(0, 0, 0, 0.0f);
+ GPU_clear(GPU_COLOR_BIT);
+
+ if ((ar->flag & RGN_FLAG_HIDDEN) == 0) {
+ float color[4];
+ UI_GetThemeColor4fv(TH_BUTBACK, color);
+ if ((U.uiflag2 & USER_REGION_OVERLAP) == 0) {
+ color[3] = 1.0f;
+ }
+ ui_draw_widget_back_color(UI_WTYPE_BOX, false, &(rcti){.xmax = ar->winx, .ymax = ar->winy}, color);
+ ED_region_panels_draw(C, ar);
+ }
+}
+
+ARegionType *ED_area_type_hud(int space_type)
+{
+ ARegionType *art = MEM_callocN(sizeof(ARegionType), __func__);
+ art->regionid = RGN_TYPE_HUD;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
+ art->layout = hud_region_layout;
+ art->draw = hud_region_draw;
+ art->init = hud_region_init;
+ art->free = hud_region_free;
+
+ hud_panels_register(art, space_type, art->regionid);
+
+ art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */
+ return art;
+}
+
+static ARegion *hud_region_add(ScrArea *sa)
+{
+ ARegion *ar = MEM_callocN(sizeof(ARegion), "area region");
+ ARegion *ar_win = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar_win) {
+ BLI_insertlinkbefore(&sa->regionbase, ar_win, ar);
+ }
+ else {
+ BLI_addtail(&sa->regionbase, ar);
+ }
+ ar->regiontype = RGN_TYPE_HUD;
+ ar->alignment = RGN_ALIGN_FLOAT;
+ ar->overlap = true;
+ ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
+
+ return ar;
+}
+
+void ED_area_type_hud_clear(wmWindowManager *wm, ScrArea *sa_keep)
+{
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ bScreen *screen = WM_window_get_active_screen(win);
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ if (sa != sa_keep) {
+ for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_HUD) {
+ if ((ar->flag & RGN_FLAG_HIDDEN) == 0) {
+ ar->flag |= RGN_FLAG_HIDDEN;
+ ED_region_tag_redraw(ar);
+ ED_area_tag_redraw(sa);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void ED_area_type_hud_ensure(bContext *C, ScrArea *sa)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ED_area_type_hud_clear(wm, sa);
+
+ ARegionType *art = BKE_regiontype_from_id(sa->type, RGN_TYPE_HUD);
+ if (art == NULL) {
+ return;
+ }
+
+ bool init = false;
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HUD);
+ if (!last_redo_poll(C)) {
+ if (ar) {
+ ED_region_tag_redraw(ar);
+ ar->flag |= RGN_FLAG_HIDDEN;
+ }
+ return;
+ }
+
+ if (ar == NULL) {
+ init = true;
+ ar = hud_region_add(sa);
+ ar->type = art;
+ }
+
+ ED_region_init(ar);
+ ED_region_tag_redraw(ar);
+
+ /* Reset zoom level (not well supported). */
+ ar->v2d.cur = ar->v2d.tot = (rctf){.xmax = ar->winx, .ymax = ar->winy};
+ ar->v2d.minzoom = 1.0f;
+ ar->v2d.maxzoom = 1.0f;
+
+ /* Let 'ED_area_update_region_sizes' do the work of placing the region.
+ * Otherwise we could set the 'ar->winrct' & 'ar->winx/winy' here. */
+ if (init) {
+ sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
+ }
+ else {
+ if (ar->flag & RGN_FLAG_HIDDEN) {
+ sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
+ }
+ ar->flag &= ~RGN_FLAG_HIDDEN;
+ }
+
+ {
+ ARegion *ar_op = CTX_wm_region(C);
+ BLI_assert((ar_op == NULL) || (ar_op->regiontype != RGN_TYPE_HUD));
+ struct HudRegionData *hrd = ar->regiondata;
+ if (hrd == NULL) {
+ hrd = MEM_callocN(sizeof(*hrd), __func__);
+ ar->regiondata = hrd;
+ }
+ if (ar_op) {
+ hrd->regionid = ar_op->regiontype;
+ }
+ else {
+ hrd->regionid = -1;
+ }
+ }
+
+ /* XXX, should be handled in more general way. */
+ ar->visible = !((ar->flag & RGN_FLAG_HIDDEN) || (ar->flag & RGN_FLAG_TOO_SMALL));
+
+ /* We shouldn't need to do this every time :S */
+ /* XXX, this is evil! - it also makes the menu show on first draw. :( */
+ ARegion *ar_prev = CTX_wm_region(C);
+ CTX_wm_region_set((bContext *)C, ar);
+ hud_region_layout(C, ar);
+ CTX_wm_region_set((bContext *)C, ar_prev);
+}
+
+/** \} */
diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.c
index 41001d65d82..504e1807a8f 100644
--- a/source/blender/editors/interface/interface_region_menu_pie.c
+++ b/source/blender/editors/interface/interface_region_menu_pie.c
@@ -76,7 +76,7 @@ static uiBlock *ui_block_func_PIE(bContext *UNUSED(C), uiPopupBlockHandle *handl
uiPieMenu *pie = arg_pie;
int minwidth, width, height;
- minwidth = 50;
+ minwidth = UI_MENU_WIDTH_MIN;
block = pie->block_radial;
/* in some cases we create the block before the region,
@@ -202,7 +202,6 @@ void UI_pie_menu_end(bContext *C, uiPieMenu *pie)
menu, WM_HANDLER_ACCEPT_DBL_CLICK);
WM_event_add_mousemove(C);
- menu->can_refresh = false;
MEM_freeN(pie);
}
diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c
index fa7113f195e..b9222a75803 100644
--- a/source/blender/editors/interface/interface_region_menu_popup.c
+++ b/source/blender/editors/interface/interface_region_menu_popup.c
@@ -191,7 +191,13 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
if (pup->but) {
/* minimum width to enforece */
- minwidth = BLI_rctf_size_x(&pup->but->rect);
+ if (pup->but->drawstr[0]) {
+ minwidth = BLI_rctf_size_x(&pup->but->rect);
+ }
+ else {
+ /* For buttons with no text, use the minimum (typically icon only). */
+ minwidth = UI_MENU_WIDTH_MIN;
+ }
/* settings (typically rna-enum-popups) show above the button,
* menu's like file-menu, show below */
@@ -209,7 +215,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
}
}
else {
- minwidth = 50;
+ minwidth = UI_MENU_WIDTH_MIN;
direction = UI_DIR_DOWN;
}
@@ -284,7 +290,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
/* for a header menu we set the direction automatic */
if (!pup->slideout && flip) {
ScrArea *sa = CTX_wm_area(C);
- if (sa && sa->headertype == HEADERDOWN) {
+ 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);
@@ -359,7 +365,6 @@ uiPopupBlockHandle *ui_popup_menu_create(
WM_event_add_mousemove(C);
}
- handle->can_refresh = false;
MEM_freeN(pup);
return handle;
@@ -450,7 +455,6 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
UI_popup_handlers_add(C, &window->modalhandlers, menu, 0);
WM_event_add_mousemove(C);
- menu->can_refresh = false;
MEM_freeN(pup);
}
@@ -569,6 +573,7 @@ void UI_popup_block_invoke_ex(bContext *C, uiBlockCreateFunc func, void *arg, co
handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg);
handle->popup = true;
+ handle->can_refresh = true;
handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL;
handle->opcontext = opcontext;
@@ -591,6 +596,7 @@ void UI_popup_block_ex(
handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg);
handle->popup = true;
handle->retvalue = 1;
+ handle->can_refresh = true;
handle->popup_op = op;
handle->popup_arg = arg;
@@ -611,6 +617,7 @@ void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, int
handle = ui_popup_block_create(C, NULL, NULL, func, NULL, op);
handle->popup = 1;
handle->retvalue = 1;
+ handle->can_refresh = true;
handle->popup_arg = op;
handle->popup_func = operator_cb;
@@ -627,11 +634,13 @@ void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block)
/* if loading new .blend while popup is open, window will be NULL */
if (block->handle) {
if (win) {
+ const bScreen *screen = WM_window_get_active_screen(win);
+
UI_popup_handlers_remove(&win->modalhandlers, block->handle);
ui_popup_block_free(C, block->handle);
/* In the case we have nested popups, closing one may need to redraw another, see: T48874 */
- for (ARegion *ar = win->screen->regionbase.first; ar; ar = ar->next) {
+ for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) {
ED_region_tag_refresh_ui(ar);
}
}
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
new file mode 100644
index 00000000000..35856b6c8b2
--- /dev/null
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -0,0 +1,396 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/interface/interface_region_popover.c
+ * \ingroup edinterface
+ *
+ * Pop-Over Region
+ *
+ * \note This is very close to 'interface_region_menu_popup.c'
+ *
+ * We could even merge them, however menu logic is already over-loaded.
+ * PopOver's have the following differences.
+ *
+ * - UI is not constrained to a list.
+ * - Pressing a button won't close the pop-over.
+ * - Different draw style (to show this is has different behavior from a menu).
+ * - #PanelType are used instead of #MenuType.
+ * - No menu flipping support.
+ * - No moving the menu to fit the mouse cursor.
+ * - No key accelerators to access menu items
+ * (if we add support they would work differently).
+ * - No arrow key navigation.
+ * - No menu memory.
+ * - No title.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_userdef_types.h"
+
+#include "BLI_listbase.h"
+
+#include "BLI_rect.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_report.h"
+
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+
+#include "UI_interface.h"
+
+#include "interface_intern.h"
+#include "interface_regions_intern.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Popup Menu with Callback or String
+ * \{ */
+
+struct uiPopover {
+ uiBlock *block;
+ uiLayout *layout;
+ uiBut *but;
+
+ /* Needed for keymap removal. */
+ wmWindow *window;
+ wmKeyMap *keymap;
+ struct wmEventHandler *keymap_handler;
+
+ uiMenuCreateFunc menu_func;
+ void *menu_arg;
+
+ /* Size in pixels (ui scale applied). */
+ int ui_size_x;
+
+#ifdef USE_UI_POPOVER_ONCE
+ bool is_once;
+#endif
+};
+
+static void ui_popover_create_block(bContext *C, uiPopover *pup, int opcontext)
+{
+ BLI_assert(pup->ui_size_x != 0);
+
+ uiStyle *style = UI_style_get_dpi();
+ pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS);
+ pup->layout = UI_block_layout(
+ pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0,
+ pup->ui_size_x, 0, MENU_PADDING, style);
+
+ uiLayoutSetOperatorContext(pup->layout, opcontext);
+
+ if (pup->but) {
+ if (pup->but->context) {
+ uiLayoutContextCopy(pup->layout, pup->but->context);
+ }
+ }
+
+ pup->block->flag |= UI_BLOCK_NO_FLIP;
+}
+
+static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
+{
+ uiPopover *pup = arg_pup;
+
+ /* Create UI block and layout now if it wasn't done between begin/end. */
+ if (!pup->layout) {
+ ui_popover_create_block(C, pup, WM_OP_INVOKE_REGION_WIN);
+
+ if (pup->menu_func) {
+ pup->block->handle = handle;
+ pup->menu_func(C, pup->layout, pup->menu_arg);
+ pup->block->handle = NULL;
+ }
+
+ pup->layout = NULL;
+ }
+
+ /* Setup and resolve UI layout for block. */
+ uiBlock *block = pup->block;
+ int width, height;
+
+ UI_block_region_set(block, handle->region);
+ UI_block_layout_resolve(block, &width, &height);
+ UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_POPOVER);
+#ifdef USE_UI_POPOVER_ONCE
+ if (pup->is_once) {
+ UI_block_flag_enable(block, UI_BLOCK_POPOVER_ONCE);
+ }
+#endif
+ UI_block_direction_set(block, UI_DIR_DOWN | UI_DIR_CENTER_X);
+
+ const int block_margin = U.widget_unit / 2;
+
+ if (pup->but) {
+ /* For a header menu we set the direction automatic. */
+ block->minbounds = BLI_rctf_size_x(&pup->but->rect);
+ UI_block_bounds_set_normal(block, block_margin);
+
+ /* If menu slides out of other menu, override direction. */
+ bool slideout = false; //ui_block_is_menu(pup->but->block);
+ if (slideout)
+ 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, &center[0], &center[1]);
+ /* These variables aren't used for popovers, we could add new variables if there is a conflict. */
+ 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;
+ }
+
+ if (!slideout) {
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ if (ar && ar->panels.first) {
+ /* For regions with panels, prefer to open to top so we can
+ * see the values of the buttons below changing. */
+ UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
+ }
+ else if (sa && ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) {
+ /* Prefer popover from header to be positioned into the editor. */
+ 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. */
+ int offset[2] = {0, 0};
+ UI_block_flag_enable(block, UI_BLOCK_LOOP);
+ UI_block_direction_set(block, block->direction);
+ block->minbounds = UI_MENU_WIDTH_MIN;
+ bool use_place_under_active = !handle->refresh;
+
+ if (use_place_under_active) {
+ uiBut *but = NULL;
+ for (but = block->buttons.first; but; but = but->next) {
+ if (but->flag & (UI_SELECT | UI_SELECT_DRAW)) {
+ break;
+ }
+ }
+
+ if (but) {
+ offset[0] = -(but->rect.xmin + 0.8f * BLI_rctf_size_x(&but->rect));
+ offset[1] = -(but->rect.ymin + 0.5f * BLI_rctf_size_y(&but->rect));
+ }
+ }
+
+ UI_block_bounds_set_popup(block, block_margin, offset[0], offset[1]);
+ }
+
+ return block;
+}
+
+static void ui_block_free_func_POPOVER(uiPopupBlockHandle *UNUSED(handle), void *arg_pup)
+{
+ uiPopover *pup = arg_pup;
+ if (pup->keymap != NULL) {
+ wmWindow *window = pup->window;
+ WM_event_remove_keymap_handler(&window->modalhandlers, pup->keymap);
+ }
+ MEM_freeN(pup);
+}
+
+uiPopupBlockHandle *ui_popover_panel_create(
+ bContext *C, ARegion *butregion, uiBut *but,
+ uiMenuCreateFunc menu_func, void *arg)
+{
+ /* Create popover, buttons are created from callback. */
+ uiPopover *pup = MEM_callocN(sizeof(uiPopover), __func__);
+ pup->but = but;
+
+ /* FIXME: maybe one day we want non panel popovers? */
+ {
+ int ui_units_x = ((PanelType *)arg)->ui_units_x;
+ pup->ui_size_x = U.widget_unit * (ui_units_x ? ui_units_x : UI_POPOVER_WIDTH_UNITS);
+ }
+
+ pup->menu_func = menu_func;
+ pup->menu_arg = arg;
+
+#ifdef USE_UI_POPOVER_ONCE
+ pup->is_once = true;
+#endif
+
+ /* Create popup block. */
+ uiPopupBlockHandle *handle;
+ handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPOVER, pup);
+ handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
+ handle->can_refresh = true;
+
+ /* Add handlers. If attached to a button, the button will already
+ * add a modal handler and pass on events. */
+ if (!but) {
+ wmWindow *window = CTX_wm_window(C);
+ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
+ WM_event_add_mousemove(C);
+ handle->popup = true;
+ }
+
+ return handle;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Standard Popover Panels
+ * \{ */
+
+int UI_popover_panel_invoke(
+ bContext *C, int space_id, int region_id, const char *idname,
+ bool keep_open, ReportList *reports)
+{
+ uiLayout *layout;
+ PanelType *pt = UI_paneltype_find(space_id, region_id, idname);
+ if (pt == NULL) {
+ BKE_reportf(
+ reports, RPT_ERROR,
+ "Panel \"%s\" not found (space %d, region %d)",
+ idname, space_id, region_id);
+ return OPERATOR_CANCELLED;
+ }
+
+ if (pt->poll && (pt->poll(C, pt) == false)) {
+ /* cancel but allow event to pass through, just like operators do */
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ if (keep_open) {
+ ui_popover_panel_create(C, NULL, NULL, ui_item_paneltype_func, pt);
+ }
+ else {
+ uiPopover *pup = UI_popover_begin(C, U.widget_unit * pt->ui_units_x);
+ layout = UI_popover_layout(pup);
+ UI_paneltype_draw(C, pt, layout);
+ UI_popover_end(C, pup, NULL);
+ }
+
+ return OPERATOR_INTERFACE;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Popup Menu API with begin & end
+ * \{ */
+
+/**
+ * Only return handler, and set optional title.
+ */
+uiPopover *UI_popover_begin(bContext *C, int ui_size_x)
+{
+ uiPopover *pup = MEM_callocN(sizeof(uiPopover), "popover menu");
+ if (ui_size_x == 0) {
+ ui_size_x = U.widget_unit * UI_POPOVER_WIDTH_UNITS;
+ }
+ pup->ui_size_x = ui_size_x;
+
+ /* Opertor context default same as menus, change if needed. */
+ ui_popover_create_block(C, pup, WM_OP_EXEC_REGION_WIN);
+
+ /* create in advance so we can let buttons point to retval already */
+ pup->block->handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
+
+ return pup;
+}
+
+static void popover_keymap_fn(wmKeyMap *UNUSED(keymap), wmKeyMapItem *UNUSED(kmi), void *user_data)
+{
+ uiPopover *pup = user_data;
+ pup->block->handle->menuretval = UI_RETURN_OK;
+}
+
+/* set the whole structure to work */
+void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap)
+{
+ wmWindow *window = CTX_wm_window(C);
+ /* Create popup block. No refresh support since the buttons were created
+ * between begin/end and we have no callback to recreate them. */
+ uiPopupBlockHandle *handle;
+
+ if (keymap) {
+ /* Add so we get keymaps shown in the buttons. */
+ UI_block_flag_enable(pup->block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS);
+ pup->keymap = keymap;
+ pup->keymap_handler = WM_event_add_keymap_handler_priority(&window->modalhandlers, keymap, 0);
+ WM_event_set_keymap_handler_callback(pup->keymap_handler, popover_keymap_fn, pup);
+ }
+
+ handle = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPOVER, pup);
+ handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
+
+ /* Add handlers. */
+ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
+ WM_event_add_mousemove(C);
+ handle->popup = true;
+
+ /* Re-add so it gets priority. */
+ if (keymap) {
+ BLI_remlink(&window->modalhandlers, pup->keymap_handler);
+ BLI_addhead(&window->modalhandlers, pup->keymap_handler);
+ }
+
+ pup->window = window;
+
+ /* TODO(campbell): we may want to make this configurable.
+ * The begin/end stype of calling popups doesn't allow to 'can_refresh' to be set.
+ * For now close this style of popvers when accessed. */
+ UI_block_flag_disable(pup->block, UI_BLOCK_KEEP_OPEN);
+
+ /* panels are created flipped (from event handling pov) */
+ pup->block->flag ^= UI_BLOCK_IS_FLIP;
+}
+
+uiLayout *UI_popover_layout(uiPopover *pup)
+{
+ return pup->layout;
+}
+
+#ifdef USE_UI_POPOVER_ONCE
+void UI_popover_once_clear(uiPopover *pup)
+{
+ pup->is_once = false;
+}
+#endif
+
+/** \} */
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index 656c59055af..1bbf2242c5d 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -48,7 +48,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "wm_subwindow.h"
#include "UI_interface.h"
@@ -64,13 +63,13 @@
/**
* Translate any popup regions (so we can drag them).
*/
-void ui_popup_translate(bContext *C, ARegion *ar, const int mdiff[2])
+void ui_popup_translate(ARegion *ar, const int mdiff[2])
{
uiBlock *block;
BLI_rcti_translate(&ar->winrct, UNPACK2(mdiff));
- ED_region_update_rect(C, ar);
+ ED_region_update_rect(ar);
ED_region_tag_redraw(ar);
@@ -85,32 +84,41 @@ 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) {
+ if (block->content_hints & BLOCK_CONTAINS_SUBMENU_BUT) {
+ bt->rect.xmax += UI_MENU_SUBMENU_PADDING;
+ }
BLI_rctf_union(&block->rect, &bt->rect);
}
}
@@ -121,34 +129,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_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 > 0.0f) left = 1;
- if (butrct.xmax + size_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,65 +190,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;
- else offset_x = butrct.xmin - block->rect.xmin;
- /* 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;
- else offset_x = butrct.xmin - block->rect.xmin;
- /* 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;
+ }
- /* 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)
- }
- }
+ /* Compute offset based on direction. */
+ int offset_x = 0, offset_y = 0;
-#if 0 /* seems redundant and causes issues with blocks inside big regions */
- /* or no space left or right */
- if (left == 0 && right == 0) {
- if (dir1 == UI_DIR_UP || dir1 == UI_DIR_DOWN) {
- /* align with left size of screen */
- offset_x = -block->rect.xmin + 5;
- }
+ 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) {
+ /* TODO: still do */
+ 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) {
+ /* TODO: still do */
+ UI_block_order_flip(block);
}
-#endif
-
-#if 0
- /* clamp to window bounds, could be made into an option if its ever annoying */
- if ( (offscreen = (block->rect.ymin + offset_y)) < 0) offset_y -= offscreen; /* bottom */
- else if ((offscreen = (block->rect.ymax + offset_y) - winy) > 0) offset_y -= offscreen; /* top */
- if ( (offscreen = (block->rect.xmin + offset_x)) < 0) offset_x -= offscreen; /* left */
- else if ((offscreen = (block->rect.xmax + offset_x) - winx) > 0) offset_x -= offscreen; /* right */
-#endif
}
- /* apply offset, buttons in window coords */
+ /* 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);
+ }
- for (bt = block->buttons.first; bt; bt = bt->next) {
+ /* Apply offset, buttons in window coords. */
+ for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
ui_block_to_window_rctf(butregion, but->block, &bt->rect, &bt->rect);
BLI_rctf_translate(&bt->rect, offset_x, offset_y);
@@ -251,7 +251,7 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
BLI_rctf_translate(&block->rect, offset_x, offset_y);
- /* safety calculus */
+ /* Safety calculus. */
{
const float midx = BLI_rctf_cent_x(&butrct);
const float midy = BLI_rctf_cent_y(&butrct);
@@ -281,7 +281,7 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
}
/* keep a list of these, needed for pulldown menus */
- saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct");
+ uiSafetyRct *saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct");
saferct->parent = butrct;
saferct->safety = block->safety;
BLI_freelistN(&block->saferct);
@@ -295,7 +295,7 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
/** \name Menu Block Creation
* \{ */
-static void ui_block_region_draw(const bContext *C, ARegion *ar)
+static void ui_block_region_refresh(const bContext *C, ARegion *ar)
{
ScrArea *ctx_area = CTX_wm_area(C);
ARegion *ctx_region = CTX_wm_region(C);
@@ -309,9 +309,11 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar)
ar->do_draw &= ~RGN_DRAW_REFRESH_UI;
for (block = ar->uiblocks.first; block; block = block_next) {
block_next = block->next;
- if (block->handle->can_refresh) {
- handle_ctx_area = block->handle->ctx_area;
- handle_ctx_region = block->handle->ctx_region;
+ uiPopupBlockHandle *handle = block->handle;
+
+ if (handle->can_refresh) {
+ handle_ctx_area = handle->ctx_area;
+ handle_ctx_region = handle->ctx_region;
if (handle_ctx_area) {
CTX_wm_area_set((bContext *)C, handle_ctx_area);
@@ -319,13 +321,21 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar)
if (handle_ctx_region) {
CTX_wm_region_set((bContext *)C, handle_ctx_region);
}
- ui_popup_block_refresh((bContext *)C, block->handle, NULL, NULL);
+
+ uiBut *but = handle->popup_create_vars.but;
+ ARegion *butregion = handle->popup_create_vars.butregion;
+ ui_popup_block_refresh((bContext *)C, handle, butregion, but);
}
}
}
CTX_wm_area_set((bContext *)C, ctx_area);
CTX_wm_region_set((bContext *)C, ctx_region);
+}
+
+static void ui_block_region_draw(const bContext *C, ARegion *ar)
+{
+ uiBlock *block;
for (block = ar->uiblocks.first; block; block = block->next)
UI_block_draw(C, block);
@@ -335,7 +345,7 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar)
* Use to refresh centered popups on screen resizing (for splash).
*/
static void ui_block_region_popup_window_listener(
- bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+ wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene))
{
switch (wmn->category) {
case NC_WINDOW:
@@ -455,8 +465,6 @@ uiBlock *ui_popup_block_refresh(
bContext *C, uiPopupBlockHandle *handle,
ARegion *butregion, uiBut *but)
{
- BLI_assert(handle->can_refresh == true);
-
const int margin = UI_POPUP_MARGIN;
wmWindow *window = CTX_wm_window(C);
ARegion *ar = handle->region;
@@ -468,6 +476,10 @@ uiBlock *ui_popup_block_refresh(
uiBlock *block_old = ar->uiblocks.first;
uiBlock *block;
+ handle->refresh = (block_old != NULL);
+
+ BLI_assert(!handle->refresh || handle->can_refresh);
+
#ifdef DEBUG
wmEvent *event_back = window->eventstate;
#endif
@@ -513,7 +525,7 @@ uiBlock *ui_popup_block_refresh(
/* if this is being created from a button */
if (but) {
block->aspect = but->block->aspect;
- ui_block_position(window, butregion, but, block);
+ ui_popup_block_position(window, butregion, but, block);
handle->direction = block->direction;
}
else {
@@ -551,7 +563,7 @@ uiBlock *ui_popup_block_refresh(
block->pie_data.pie_center_spawned[0] += x_offset;
block->pie_data.pie_center_spawned[1] += y_offset;
- ui_block_translate(block, x_offset, y_offset);
+ UI_block_translate(block, x_offset, y_offset);
if (U.pie_initial_timeout > 0)
block->pie_data.flags |= UI_PIE_INITIAL_DIRECTION;
@@ -576,6 +588,17 @@ uiBlock *ui_popup_block_refresh(
else {
/* clip block with window boundary */
ui_popup_block_clip(window, block);
+
+ /* Avoid menu moving down and losing cursor focus by keeping it at
+ * the same height. */
+ if (handle->refresh && handle->prev_block_rect.ymax > block->rect.ymax) {
+ float offset = handle->prev_block_rect.ymax - block->rect.ymax;
+ UI_block_translate(block, 0, offset);
+ block->rect.ymin = handle->prev_block_rect.ymin;
+ }
+
+ handle->prev_block_rect = block->rect;
+
/* the block and buttons were positioned in window space as in 2.4x, now
* these menu blocks are regions so we bring it back to region space.
* additionally we add some padding for the menu shadow or rounded menus */
@@ -584,7 +607,15 @@ uiBlock *ui_popup_block_refresh(
ar->winrct.ymin = block->rect.ymin - margin;
ar->winrct.ymax = block->rect.ymax + UI_POPUP_MENU_TOP;
- ui_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
+ UI_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
+
+ /* apply scroll offset */
+ if (handle->scrolloffset != 0.0f) {
+ for (uiBut *bt = block->buttons.first; bt; bt = bt->next) {
+ bt->rect.ymin += handle->scrolloffset;
+ bt->rect.ymax += handle->scrolloffset;
+ }
+ }
}
if (block_old) {
@@ -597,17 +628,15 @@ uiBlock *ui_popup_block_refresh(
ui_popup_block_scrolltest(block);
/* adds subwindow */
- ED_region_init(C, ar);
+ ED_region_init(ar);
/* get winmat now that we actually have the subwindow */
- wmSubWindowSet(window, ar->swinid);
-
- wm_subwindow_matrix_get(window, ar->swinid, block->winmat);
+ wmGetProjectionMatrix(block->winmat, &ar->winrct);
/* notify change and redraw */
ED_region_tag_redraw(ar);
- ED_region_update_rect(C, ar);
+ ED_region_update_rect(ar);
#ifdef DEBUG
window->eventstate = event_back;
@@ -646,10 +675,12 @@ uiPopupBlockHandle *ui_popup_block_create(
handle->popup_create_vars.create_func = create_func;
handle->popup_create_vars.handle_create_func = handle_create_func;
handle->popup_create_vars.arg = arg;
+ handle->popup_create_vars.but = but;
handle->popup_create_vars.butregion = but ? butregion : NULL;
copy_v2_v2_int(handle->popup_create_vars.event_xy, &window->eventstate->x);
- /* caller may free vars used to create this popup, in that case this variable should be disabled. */
- handle->can_refresh = true;
+
+ /* don't allow by default, only if popup type explicitly supports it */
+ handle->can_refresh = false;
/* create area region */
ar = ui_region_temp_add(CTX_wm_screen(C));
@@ -657,6 +688,7 @@ uiPopupBlockHandle *ui_popup_block_create(
memset(&type, 0, sizeof(ARegionType));
type.draw = ui_block_region_draw;
+ type.layout = ui_block_region_refresh;
type.regionid = RGN_TYPE_TEMPORARY;
ar->type = &type;
@@ -666,7 +698,7 @@ uiPopupBlockHandle *ui_popup_block_create(
handle = block->handle;
/* keep centered on window resizing */
- if ((block->bounds_type == UI_BLOCK_BOUNDS_POPUP_CENTER) && handle->can_refresh) {
+ if (block->bounds_type == UI_BLOCK_BOUNDS_POPUP_CENTER) {
type.listener = ui_block_region_popup_window_listener;
}
@@ -675,6 +707,25 @@ uiPopupBlockHandle *ui_popup_block_create(
void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle)
{
+ /* If this popup is created from a popover which does NOT have keep-open flag set,
+ * then close the popover too. We could extend this to other popup types too. */
+ ARegion *ar = handle->popup_create_vars.butregion;
+ if (ar != NULL) {
+ for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
+ if (block->handle &&
+ (block->flag & UI_BLOCK_POPOVER) &&
+ (block->flag & UI_BLOCK_KEEP_OPEN) == 0)
+ {
+ uiPopupBlockHandle *menu = block->handle;
+ menu->menuretval = UI_RETURN_OK;
+ }
+ }
+ }
+
+ if (handle->popup_create_vars.free_func) {
+ handle->popup_create_vars.free_func(handle, handle->popup_create_vars.arg);
+ }
+
ui_popup_block_remove(C, handle);
MEM_freeN(handle);
diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c
index 8d4389c73e6..d262cbc38bd 100644
--- a/source/blender/editors/interface/interface_region_search.c
+++ b/source/blender/editors/interface/interface_region_search.c
@@ -64,6 +64,7 @@
#include "interface_intern.h"
#include "interface_regions_intern.h"
+#include "GPU_state.h"
#define MENU_BORDER (int)(0.3f * U.widget_unit)
@@ -397,15 +398,16 @@ int ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str)
return match;
}
-static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
+static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar)
{
uiSearchboxData *data = ar->regiondata;
/* pixel space */
wmOrtho2_region_pixelspace(ar);
- if (data->noback == false)
- ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */
+ if (data->noback == false) {
+ ui_draw_widget_back(UI_WTYPE_MENU_BACK, true, &data->bbox);
+ }
/* draw text */
if (data->items.totitem) {
@@ -415,6 +417,9 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
if (data->preview) {
/* draw items */
for (a = 0; a < data->items.totitem; a++) {
+ /* ensure icon is up-to-date */
+ ui_icon_ensure_deferred(C, data->items.icons[a], data->preview);
+
ui_searchbox_butrect(&rect, data, a);
/* widget itself */
@@ -426,15 +431,15 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
/* indicate more */
if (data->items.more) {
ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw(rect.xmax - 18, rect.ymin - 7, ICON_TRIA_DOWN);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
if (data->items.offset) {
ui_searchbox_butrect(&rect, data, 0);
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw(rect.xmin, rect.ymax - 9, ICON_TRIA_UP);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
@@ -452,15 +457,15 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
/* indicate more */
if (data->items.more) {
ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
if (data->items.offset) {
ui_searchbox_butrect(&rect, data, 0);
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
}
@@ -624,7 +629,7 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but
}
/* adds subwindow */
- ED_region_init(C, ar);
+ ED_region_init(ar);
/* notify change and redraw */
ED_region_tag_redraw(ar);
@@ -680,8 +685,9 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
/* pixel space */
wmOrtho2_region_pixelspace(ar);
- if (data->noback == false)
- ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */
+ if (data->noback == false) {
+ ui_draw_widget_back(UI_WTYPE_MENU_BACK, true, &data->bbox);
+ }
/* draw text */
if (data->items.totitem) {
@@ -730,15 +736,15 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
/* indicate more */
if (data->items.more) {
ui_searchbox_butrect(&rect, data, data->items.maxitem - 1);
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
if (data->items.offset) {
ui_searchbox_butrect(&rect, data, 0);
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
}
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 1eec3737215..ed83a715c7e 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -164,6 +164,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
uiWidgetColors *theme = ui_tooltip_get_theme();
rcti bbox = data->bbox;
float tip_colors[UI_TIP_LC_MAX][3];
+ unsigned char drawcol[4] = {0, 0, 0, 255}; /* to store color in while drawing (alpha is always 255) */
float *main_color = tip_colors[UI_TIP_LC_MAIN]; /* the color from the theme */
float *value_color = tip_colors[UI_TIP_LC_VALUE];
@@ -174,12 +175,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
float background_color[3];
float tone_bg;
- int i, multisample_enabled;
-
- /* disable AA, makes widgets too blurry */
- multisample_enabled = glIsEnabled(GL_MULTISAMPLE);
- if (multisample_enabled)
- glDisable(GL_MULTISAMPLE);
+ int i;
wmOrtho2_region_pixelspace(ar);
@@ -232,9 +228,9 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
fstyle_header.shadowalpha = 1.0f;
fstyle_header.word_wrap = true;
+ rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_MAIN]);
UI_fontstyle_set(&fstyle_header);
- glColor3fv(tip_colors[UI_TIP_LC_MAIN]);
- UI_fontstyle_draw(&fstyle_header, &bbox, field->text);
+ UI_fontstyle_draw(&fstyle_header, &bbox, field->text, drawcol);
fstyle_header.shadow = 0;
@@ -245,8 +241,8 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
bbox.xmin += xofs;
bbox.ymax -= yofs;
- glColor3fv(tip_colors[UI_TIP_LC_ACTIVE]);
- UI_fontstyle_draw(&fstyle_header, &bbox, field->text_suffix);
+ rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_ACTIVE]);
+ UI_fontstyle_draw(&fstyle_header, &bbox, field->text_suffix, drawcol);
/* undo offset */
bbox.xmin -= xofs;
@@ -261,8 +257,8 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
UI_fontstyle_set(&fstyle_mono);
/* XXX, needed because we dont have mono in 'U.uifonts' */
BLF_size(fstyle_mono.uifont_id, fstyle_mono.points * U.pixelsize, U.dpi);
- glColor3fv(tip_colors[field->format.color_id]);
- UI_fontstyle_draw(&fstyle_mono, &bbox, field->text);
+ rgb_float_to_uchar(drawcol, tip_colors[field->format.color_id]);
+ UI_fontstyle_draw(&fstyle_mono, &bbox, field->text, drawcol);
}
else {
uiFontStyle fstyle_normal = data->fstyle;
@@ -270,9 +266,9 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
fstyle_normal.word_wrap = true;
/* draw remaining data */
+ rgb_float_to_uchar(drawcol, tip_colors[field->format.color_id]);
UI_fontstyle_set(&fstyle_normal);
- glColor3fv(tip_colors[field->format.color_id]);
- UI_fontstyle_draw(&fstyle_normal, &bbox, field->text);
+ UI_fontstyle_draw(&fstyle_normal, &bbox, field->text, drawcol);
}
bbox.ymax -= data->lineh * field->geom.lines;
@@ -284,9 +280,6 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
BLF_disable(data->fstyle.uifont_id, BLF_WORD_WRAP);
BLF_disable(blf_mono_font, BLF_WORD_WRAP);
-
- if (multisample_enabled)
- glEnable(GL_MULTISAMPLE);
}
static void ui_tooltip_region_free_cb(ARegion *ar)
@@ -313,6 +306,63 @@ static void ui_tooltip_region_free_cb(ARegion *ar)
/** \name ToolTip Creation
* \{ */
+static uiTooltipData *ui_tooltip_data_from_keymap(bContext *C, wmKeyMap *keymap)
+{
+ char buf[512];
+
+ /* create tooltip data */
+ uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
+
+ for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
+ wmOperatorType *ot = WM_operatortype_find(kmi->idname, true);
+ if (ot != NULL) {
+ /* Tip */
+ {
+ uiTooltipField *field = text_field_add(
+ data, &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_MAIN,
+ .is_pad = true,
+ });
+ field->text = BLI_strdup(ot->description[0] ? ot->description : ot->name);
+ }
+ /* Shortcut */
+ {
+ uiTooltipField *field = text_field_add(
+ data, &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_NORMAL,
+ });
+ bool found = false;
+ if (WM_keymap_item_to_string(kmi, false, buf, sizeof(buf))) {
+ found = true;
+ }
+ field->text = BLI_sprintfN(TIP_("Shortcut: %s"), found ? buf : "None");
+ }
+
+ /* Python */
+ {
+ uiTooltipField *field = text_field_add(
+ data, &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_PYTHON,
+ });
+ char *str = WM_operator_pystring_ex(C, NULL, false, false, ot, kmi->ptr);
+ WM_operator_pystring_abbreviate(str, 32);
+ field->text = BLI_sprintfN(TIP_("Python: %s"), str);
+ MEM_freeN(str);
+ }
+ }
+ }
+ if (data->fields_len == 0) {
+ MEM_freeN(data);
+ return NULL;
+ }
+ else {
+ return data;
+ }
+}
+
static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
{
uiStringInfo but_tip = {BUT_GET_TIP, NULL};
@@ -463,7 +513,7 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
WM_operator_pystring_abbreviate(str, 32);
/* operator info */
- if ((U.flag & USER_TOOLTIPS_PYTHON) == 0) {
+ if (U.flag & USER_TOOLTIPS_PYTHON) {
uiTooltipField *field = text_field_add(
data, &(uiTooltipFormat){
.style = UI_TIP_STYLE_MONO,
@@ -501,7 +551,7 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
}
}
- if ((U.flag & USER_TOOLTIPS_PYTHON) == 0 && !but->optype && rna_struct.strinfo) {
+ if ((U.flag & USER_TOOLTIPS_PYTHON) && !but->optype && rna_struct.strinfo) {
{
uiTooltipField *field = text_field_add(
data, &(uiTooltipFormat){
@@ -565,6 +615,112 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
}
}
+static uiTooltipData *ui_tooltip_data_from_manipulator(bContext *C, wmManipulator *mpr)
+{
+ uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
+
+ /* TODO(campbell): a way for manipulators to have their own descriptions (low priority). */
+
+ /* Operator Actions */
+ {
+ bool use_drag = mpr->drag_part != -1 && mpr->highlight_part != mpr->drag_part;
+
+ const struct {
+ int part;
+ const char *prefix;
+ } mpop_actions[] = {
+ {
+ .part = mpr->highlight_part,
+ .prefix = use_drag ? TIP_("Click") : NULL,
+ }, {
+ .part = use_drag ? mpr->drag_part : -1,
+ .prefix = use_drag ? TIP_("Drag") : NULL,
+ },
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(mpop_actions); i++) {
+ wmManipulatorOpElem *mpop = (mpop_actions[i].part != -1) ? WM_manipulator_operator_get(mpr, mpop_actions[i].part) : NULL;
+ if (mpop != NULL) {
+ /* Description */
+ const char *info = RNA_struct_ui_description(mpop->type->srna);
+ if (!(info && info[0])) {
+ info = RNA_struct_ui_name(mpop->type->srna);
+ }
+
+ if (info && info[0]) {
+ char *text = NULL;
+ if (mpop_actions[i].prefix != NULL) {
+ text = BLI_sprintfN("%s: %s", mpop_actions[i].prefix, info);
+ }
+ else {
+ text = BLI_strdup(info);
+ }
+
+ if (text != NULL) {
+ uiTooltipField *field = text_field_add(
+ data, &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_HEADER,
+ .color_id = UI_TIP_LC_VALUE,
+ .is_pad = true,
+ });
+ field->text = text;
+ }
+ }
+
+ /* Shortcut */
+ {
+ bool found = false;
+ IDProperty *prop = mpop->ptr.data;
+ char buf[128];
+ if (WM_key_event_operator_string(
+ C, mpop->type->idname, WM_OP_INVOKE_DEFAULT, prop, true,
+ buf, ARRAY_SIZE(buf)))
+ {
+ found = true;
+ }
+ uiTooltipField *field = text_field_add(
+ data, &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_VALUE,
+ .is_pad = true,
+ });
+ field->text = BLI_sprintfN(TIP_("Shortcut: %s"), found ? buf : "None");
+ }
+ }
+ }
+ }
+
+ /* Property Actions */
+ if (mpr->type->target_property_defs_len) {
+ wmManipulatorProperty *mpr_prop_array = WM_manipulator_target_property_array(mpr);
+ for (int i = 0; i < mpr->type->target_property_defs_len; i++) {
+ /* TODO(campbell): function callback descriptions. */
+ wmManipulatorProperty *mpr_prop = &mpr_prop_array[i];
+ if (mpr_prop->prop != NULL) {
+ const char *info = RNA_property_ui_description(mpr_prop->prop);
+ if (info && info[0]) {
+ uiTooltipField *field = text_field_add(
+ data, &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_VALUE,
+ .is_pad = true,
+ });
+ field->text = BLI_strdup(info);
+ }
+ }
+ }
+ }
+
+ if (data->fields_len == 0) {
+ MEM_freeN(data);
+ return NULL;
+ }
+ else {
+ return data;
+ }
+}
+
+
static ARegion *ui_tooltip_create_with_data(
bContext *C, uiTooltipData *data,
const float init_position[2],
@@ -711,7 +867,7 @@ static ARegion *ui_tooltip_create_with_data(
}
/* adds subwindow */
- ED_region_init(C, ar);
+ ED_region_init(ar);
/* notify change and redraw */
ED_region_tag_redraw(ar);
@@ -738,6 +894,28 @@ ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *b
}
uiTooltipData *data = NULL;
+ /* custom tips for pre-defined operators */
+ if (but->optype) {
+ /* TODO(campbell): we now use 'WM_OT_tool_set_by_name', this logic will be moved into the status bar. */
+ if (false && STREQ(but->optype->idname, "WM_OT_tool_set")) {
+ char keymap[64] = "";
+ RNA_string_get(but->opptr, "keymap", keymap);
+ if (keymap[0]) {
+ ScrArea *sa = CTX_wm_area(C);
+ /* It happens in rare cases, for tooltips originated from the toolbar.
+ * It is hard to reproduce, but it happens when the mouse is nowhere near the actual tool. */
+ if (sa == NULL) {
+ return NULL;
+ }
+ wmKeyMap *km = WM_keymap_find_all(C, keymap, sa->spacetype, RGN_TYPE_WINDOW);
+ if (km != NULL) {
+ data = ui_tooltip_data_from_keymap(C, km);
+ }
+ }
+ }
+ }
+ /* toolsystem exception */
+
if (data == NULL) {
data = ui_tooltip_data_from_button(C, but);
}
@@ -756,6 +934,23 @@ ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *b
return ui_tooltip_create_with_data(C, data, init_position, aspect);
}
+ARegion *UI_tooltip_create_from_manipulator(bContext *C, wmManipulator *mpr)
+{
+ wmWindow *win = CTX_wm_window(C);
+ const float aspect = 1.0f;
+ float init_position[2];
+
+ uiTooltipData *data = ui_tooltip_data_from_manipulator(C, mpr);
+ if (data == NULL) {
+ return NULL;
+ }
+
+ init_position[0] = win->eventstate->x;
+ init_position[1] = win->eventstate->y;
+
+ return ui_tooltip_create_with_data(C, data, init_position, aspect);
+}
+
void UI_tooltip_free(bContext *C, bScreen *sc, ARegion *ar)
{
ui_region_temp_remove(C, sc, ar);
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 2c3d94214d1..0decc937e19 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -61,6 +61,9 @@ ARegion *ui_region_temp_add(bScreen *sc)
void ui_region_temp_remove(bContext *C, bScreen *sc, ARegion *ar)
{
wmWindow *win = CTX_wm_window(C);
+
+ BLI_assert(ar->regiontype == RGN_TYPE_TEMPORARY);
+ BLI_assert(BLI_findindex(&sc->regionbase, ar) != -1);
if (win)
wm_draw_region_clear(win, ar);
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index eabc5150424..36ad516bf7f 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -149,7 +149,7 @@ static uiFont *uifont_to_blfont(int id)
void UI_fontstyle_draw_ex(
- const uiFontStyle *fs, const rcti *rect, const char *str,
+ const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4],
size_t len, float *r_xofs, float *r_yofs)
{
int xofs = 0, yofs;
@@ -196,6 +196,7 @@ void UI_fontstyle_draw_ex(
/* clip is very strict, so we give it some space */
BLF_clipping(fs->uifont_id, rect->xmin - 2, rect->ymin - 4, rect->xmax + 1, rect->ymax + 4);
BLF_position(fs->uifont_id, rect->xmin + xofs, rect->ymin + yofs, 0.0f);
+ BLF_color4ubv(fs->uifont_id, col);
BLF_draw(fs->uifont_id, str, len);
@@ -205,17 +206,17 @@ void UI_fontstyle_draw_ex(
*r_yofs = yofs;
}
-void UI_fontstyle_draw(const uiFontStyle *fs, const rcti *rect, const char *str)
+void UI_fontstyle_draw(const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4])
{
float xofs, yofs;
UI_fontstyle_draw_ex(
- fs, rect, str,
+ fs, rect, str, col,
BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs);
}
/* drawn same as above, but at 90 degree angle */
-void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const char *str)
+void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4])
{
float height;
int xofs, yofs;
@@ -249,6 +250,7 @@ void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const ch
BLF_enable(fs->uifont_id, BLF_ROTATION);
BLF_rotation(fs->uifont_id, angle);
+ BLF_color4ubv(fs->uifont_id, col);
if (fs->shadow) {
BLF_enable(fs->uifont_id, BLF_SHADOW);
@@ -275,13 +277,14 @@ void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const ch
*
* For drawing on-screen labels.
*/
-void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str)
+void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str, const unsigned char col[4])
{
if (fs->kerning == 1)
BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
UI_fontstyle_set(fs);
BLF_position(fs->uifont_id, x, y, 0.0f);
+ BLF_color4ubv(fs->uifont_id, col);
BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
if (fs->kerning == 1)
@@ -293,7 +296,7 @@ void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const cha
*/
void UI_fontstyle_draw_simple_backdrop(
const uiFontStyle *fs, float x, float y, const char *str,
- const unsigned char fg[4], const unsigned char bg[4])
+ const float col_fg[4], const float col_bg[4])
{
if (fs->kerning == 1)
BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
@@ -307,21 +310,19 @@ void UI_fontstyle_draw_simple_backdrop(
const float margin = height / 4.0f;
/* backdrop */
- glColor4ubv(bg);
+ float color[4] = { col_bg[0], col_bg[1], col_bg[2], 0.5f };
- UI_draw_roundbox_corner_set(UI_CNR_ALL | UI_RB_ALPHA);
- UI_draw_roundbox(
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_aa(true,
x - margin,
(y + decent) - margin,
x + width + margin,
(y + decent) + height + margin,
- margin);
-
- glColor4ubv(fg);
+ margin, color);
}
-
BLF_position(fs->uifont_id, x, y, 0.0f);
+ BLF_color4fv(fs->uifont_id, col_fg);
BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
if (fs->kerning == 1)
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index bd4bb032717..6110d5f3466 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -56,11 +56,12 @@
#include "BKE_colorband.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_idcode.h"
#include "BKE_idprop.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
+#include "BKE_library_override.h"
#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
@@ -69,9 +70,11 @@
#include "BKE_particle.h"
#include "BKE_paint.h"
#include "BKE_report.h"
-#include "BKE_sca.h"
#include "BKE_screen.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_screen.h"
#include "ED_object.h"
#include "ED_render.h"
@@ -91,11 +94,128 @@
// #define USE_OP_RESET_BUT // we may want to make this optional, disable for now.
+/* defines for templateID/TemplateSearch */
+#define TEMPLATE_SEARCH_TEXTBUT_WIDTH (UI_UNIT_X * 6)
+#define TEMPLATE_SEARCH_TEXTBUT_HEIGHT UI_UNIT_Y
+
void UI_template_fix_linking(void)
{
}
+/**
+ * Add a block button for the search menu for templateID and templateSearch.
+ */
+static void template_add_button_search_menu(
+ const bContext *C, uiLayout *layout, uiBlock *block,
+ PointerRNA *ptr, PropertyRNA *prop,
+ uiBlockCreateFunc block_func, void *block_argN, const char * const tip,
+ const bool use_previews, const bool editable)
+{
+ PointerRNA active_ptr = RNA_property_pointer_get(ptr, prop);
+ ID *id = (active_ptr.data && RNA_struct_is_ID(active_ptr.type)) ? active_ptr.data : NULL;
+ const ID *idfrom = ptr->id.data;
+ const StructRNA *type = active_ptr.type ? active_ptr.type : RNA_property_pointer_type(ptr, prop);
+ uiBut *but;
+
+ if (use_previews) {
+ ARegion *region = CTX_wm_region(C);
+ ScrArea *area = CTX_wm_area(C);
+ /* XXX ugly top-bar exception */
+ const bool use_big_size = (region->regiontype != RGN_TYPE_HEADER) && (area->spacetype != SPACE_TOPBAR); /* silly check, could be more generic */
+ /* Ugly exception for screens here, drawing their preview in icon size looks ugly/useless */
+ const bool use_preview_icon = use_big_size || (id && (GS(id->name) != ID_SCR));
+ const short width = UI_UNIT_X * (use_big_size ? 6 : 1.6f);
+ const short height = UI_UNIT_Y * (use_big_size ? 6 : 1);
+
+ but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, width, height, tip);
+ if (use_preview_icon) {
+ int icon = id ? ui_id_icon_get(C, id, use_big_size) : RNA_struct_ui_icon(type);
+ ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
+ }
+ else {
+ ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON);
+ UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
+ }
+
+ if ((idfrom && idfrom->lib) || !editable)
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ if (use_big_size) {
+ uiLayoutRow(layout, true);
+ }
+ }
+ else {
+ but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, tip);
+ ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON);
+ if (id) {
+ /* default dragging of icon for id browse buttons */
+ UI_but_drag_set_id(but, id);
+ }
+ UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
+
+ if ((idfrom && idfrom->lib) || !editable)
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+}
+
+static uiBlock *template_common_search_menu(
+ const bContext *C, ARegion *region,
+ uiButSearchFunc search_func, void *search_arg,
+ uiButHandleFunc handle_func, void *active_item,
+ const int preview_rows, const int preview_cols)
+{
+ static char search[256];
+ wmWindow *win = CTX_wm_window(C);
+ uiBlock *block;
+ uiBut *but;
+
+ /* clear initial search string, then all items show */
+ search[0] = 0;
+
+ block = UI_block_begin(C, region, "_popup", UI_EMBOSS);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU);
+
+ /* preview thumbnails */
+ if (preview_rows > 0 && preview_cols > 0) {
+ const int w = 4 * U.widget_unit * preview_cols;
+ const int h = 5 * U.widget_unit * preview_rows;
+
+ /* fake button, it holds space for search items */
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL);
+
+ but = uiDefSearchBut(
+ block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, UI_UNIT_Y,
+ preview_rows, preview_cols, "");
+ }
+ /* list view */
+ else {
+ const int searchbox_width = UI_searchbox_size_x();
+ const int searchbox_height = UI_searchbox_size_y();
+
+ /* fake button, it holds space for search items */
+ uiDefBut(
+ block, UI_BTYPE_LABEL, 0, "", 10, 15, searchbox_width, searchbox_height,
+ NULL, 0, 0, 0, 0, NULL);
+ but = uiDefSearchBut(
+ block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0,
+ searchbox_width, UI_UNIT_Y - 1, 0, 0, "");
+ }
+ UI_but_func_search_set(
+ but, ui_searchbox_create_generic, search_func,
+ search_arg, handle_func, active_item);
+
+
+ UI_block_bounds_set_normal(block, 0.3f * U.widget_unit);
+ UI_block_direction_set(block, UI_DIR_DOWN);
+
+ /* give search-field focus */
+ UI_but_focus_on_enter_event(win, but);
+ /* this type of search menu requires undo */
+ but->flag |= UI_BUT_UNDO;
+
+ return block;
+}
+
/********************** Header Template *************************/
void uiTemplateHeader(uiLayout *layout, bContext *C)
@@ -120,7 +240,7 @@ typedef struct TemplateID {
} TemplateID;
/* Search browse menu, assign */
-static void id_search_call_cb(bContext *C, void *arg_template, void *item)
+static void template_ID_set_property_cb(bContext *C, void *arg_template, void *item)
{
TemplateID *template_ui = (TemplateID *)arg_template;
@@ -231,30 +351,25 @@ static void id_search_cb_objects_from_scene(const bContext *C, void *arg_templat
}
BKE_main_id_flag_listbase(lb, LIB_TAG_DOIT, false);
- for (Base *base = scene->base.first; base; base = base->next) {
- base->object->id.tag |= LIB_TAG_DOIT;
+
+ FOREACH_SCENE_OBJECT_BEGIN(scene, ob_iter)
+ {
+ ob_iter->id.tag |= LIB_TAG_DOIT;
}
+ FOREACH_SCENE_OBJECT_END;
id_search_cb_tagged(C, arg_template, str, items);
}
/* ID Search browse menu, open */
static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
{
- static char search[256];
static TemplateID template_ui;
- PointerRNA idptr;
- wmWindow *win = CTX_wm_window(C);
- uiBlock *block;
- uiBut *but;
+ PointerRNA active_item_ptr;
void (*id_search_cb_p)(const bContext *, void *, const char *, uiSearchItems *) = id_search_cb;
- /* clear initial search string, then all items show */
- search[0] = 0;
/* arg_litem is malloced, can be freed by parent button */
template_ui = *((TemplateID *)arg_litem);
-
- /* get active id for showing first item */
- idptr = RNA_property_pointer_get(&template_ui.ptr, template_ui.prop);
+ active_item_ptr = RNA_property_pointer_get(&template_ui.ptr, template_ui.prop);
if (template_ui.filter) {
/* Currently only used for objects. */
@@ -265,47 +380,9 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
}
}
- block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
- UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU);
-
- /* preview thumbnails */
- if (template_ui.prv_rows > 0 && template_ui.prv_cols > 0) {
- int w = 4 * U.widget_unit * template_ui.prv_cols;
- int h = 5 * U.widget_unit * template_ui.prv_rows;
-
- /* fake button, it holds space for search items */
- uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL);
-
- but = uiDefSearchBut(
- block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, UI_UNIT_Y,
- template_ui.prv_rows, template_ui.prv_cols, "");
- UI_but_func_search_set(
- but, ui_searchbox_create_generic, id_search_cb_p,
- &template_ui, id_search_call_cb, idptr.data);
- }
- /* list view */
- else {
- const int searchbox_width = UI_searchbox_size_x();
- const int searchbox_height = UI_searchbox_size_y();
-
- /* fake button, it holds space for search items */
- uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 15, searchbox_width, searchbox_height, NULL, 0, 0, 0, 0, NULL);
- but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, searchbox_width, UI_UNIT_Y - 1, 0, 0, "");
- UI_but_func_search_set(
- but, ui_searchbox_create_generic, id_search_cb_p,
- &template_ui, id_search_call_cb, idptr.data);
- }
-
-
- UI_block_bounds_set_normal(block, 0.3f * U.widget_unit);
- UI_block_direction_set(block, UI_DIR_DOWN);
-
- /* give search-field focus */
- UI_but_focus_on_enter_event(win, but);
- /* this type of search menu requires undo */
- but->flag |= UI_BUT_UNDO;
-
- return block;
+ return template_common_search_menu(
+ C, ar, id_search_cb_p, &template_ui, template_ID_set_property_cb, active_item_ptr.data,
+ template_ui.prv_rows, template_ui.prv_cols);
}
/************************ ID Template ***************************/
@@ -313,36 +390,22 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
/* for new/open operators */
void UI_context_active_but_prop_get_templateID(
- bContext *C,
- PointerRNA *r_ptr, PropertyRNA **r_prop)
+ bContext *C,
+ PointerRNA *r_ptr, PropertyRNA **r_prop)
{
TemplateID *template_ui;
- ARegion *ar = CTX_wm_region(C);
- uiBlock *block;
- uiBut *but;
+ uiBut *but = UI_context_active_but_get(C);
memset(r_ptr, 0, sizeof(*r_ptr));
*r_prop = NULL;
- if (!ar)
- return;
-
- for (block = ar->uiblocks.first; block; block = block->next) {
- for (but = block->buttons.first; but; but = but->next) {
- /* find the button before the active one */
- if ((but->flag & (UI_BUT_LAST_ACTIVE | UI_ACTIVE))) {
- if (but->func_argN) {
- template_ui = but->func_argN;
- *r_ptr = template_ui->ptr;
- *r_prop = template_ui->prop;
- return;
- }
- }
- }
+ if (but && but->func_argN) {
+ template_ui = but->func_argN;
+ *r_ptr = template_ui->ptr;
+ *r_prop = template_ui->prop;
}
}
-
static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
{
TemplateID *template_ui = (TemplateID *)arg_litem;
@@ -383,14 +446,34 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
case UI_ID_LOCAL:
if (id) {
Main *bmain = CTX_data_main(C);
- if (id_make_local(bmain, id, false, false)) {
- BKE_main_id_clear_newpoins(bmain);
+ if (CTX_wm_window(C)->eventstate->shift) {
+ ID *override_id = BKE_override_static_create_from_id(bmain, id);
+ if (override_id != NULL) {
+ BKE_main_id_clear_newpoins(bmain);
+
+ /* Assign new pointer, takes care of updates/notifiers */
+ RNA_id_pointer_create(override_id, &idptr);
+ }
+ }
+ else {
+ if (id_make_local(bmain, id, false, false)) {
+ BKE_main_id_clear_newpoins(bmain);
- /* reassign to get get proper updates/notifiers */
- idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
- RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
- RNA_property_update(C, &template_ui->ptr, template_ui->prop);
+ /* reassign to get get proper updates/notifiers */
+ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
+ }
}
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
+ RNA_property_update(C, &template_ui->ptr, template_ui->prop);
+ }
+ break;
+ case UI_ID_OVERRIDE:
+ if (id && id->override_static) {
+ BKE_override_static_free(&id->override_static);
+ /* reassign to get get proper updates/notifiers */
+ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
+ RNA_property_update(C, &template_ui->ptr, template_ui->prop);
}
break;
case UI_ID_ALONE:
@@ -404,14 +487,15 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ED_object_single_user(bmain, scene, (struct Object *)id);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
else {
if (id) {
Main *bmain = CTX_data_main(C);
id_single_user(C, id, &template_ui->ptr, template_ui->prop);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
}
}
@@ -423,7 +507,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
}
}
-static const char *template_id_browse_tip(StructRNA *type)
+static const char *template_id_browse_tip(const StructRNA *type)
{
if (type) {
switch (RNA_type_to_ID_code(type)) {
@@ -437,7 +521,7 @@ static const char *template_id_browse_tip(StructRNA *type)
case ID_IM: return N_("Browse Image to be linked");
case ID_LS: return N_("Browse Line Style Data to be linked");
case ID_LT: return N_("Browse Lattice Data to be linked");
- case ID_LA: return N_("Browse Lamp Data to be linked");
+ case ID_LA: return N_("Browse Light Data to be linked");
case ID_CA: return N_("Browse Camera Data to be linked");
case ID_WO: return N_("Browse World Settings to be linked");
case ID_SCR: return N_("Choose Screen layout");
@@ -455,6 +539,8 @@ static const char *template_id_browse_tip(StructRNA *type)
case ID_PAL: return N_("Browse Palette Data to be linked");
case ID_PC: return N_("Browse Paint Curve Data to be linked");
case ID_CF: return N_("Browse Cache Files to be linked");
+ case ID_WS: return N_("Browse Workspace to be linked");
+ case ID_LP: return N_("Browse LightProbe to be linked");
}
}
return N_("Browse ID data to be linked");
@@ -474,6 +560,74 @@ static const char *template_id_context(StructRNA *type)
}
#endif
+static uiBut *template_id_def_new_but(
+ uiBlock *block, const ID *id, const TemplateID *template_ui, StructRNA *type,
+ const char * const newop, const bool editable, const bool id_open, const bool use_tab_but,
+ int but_height)
+{
+ ID *idfrom = template_ui->ptr.id.data;
+ uiBut *but;
+ const int w = id ? UI_UNIT_X : id_open ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
+ const int but_type = use_tab_but ? UI_BTYPE_TAB : UI_BTYPE_BUT;
+
+ /* i18n markup, does nothing! */
+ BLT_I18N_MSGID_MULTI_CTXT(
+ "New",
+ BLT_I18NCONTEXT_DEFAULT,
+ BLT_I18NCONTEXT_ID_SCENE,
+ BLT_I18NCONTEXT_ID_OBJECT,
+ BLT_I18NCONTEXT_ID_MESH,
+ BLT_I18NCONTEXT_ID_CURVE,
+ BLT_I18NCONTEXT_ID_METABALL,
+ BLT_I18NCONTEXT_ID_MATERIAL,
+ BLT_I18NCONTEXT_ID_TEXTURE,
+ BLT_I18NCONTEXT_ID_IMAGE,
+ BLT_I18NCONTEXT_ID_LATTICE,
+ BLT_I18NCONTEXT_ID_LAMP,
+ BLT_I18NCONTEXT_ID_CAMERA,
+ BLT_I18NCONTEXT_ID_WORLD,
+ BLT_I18NCONTEXT_ID_SCREEN,
+ BLT_I18NCONTEXT_ID_TEXT,
+ );
+ BLT_I18N_MSGID_MULTI_CTXT(
+ "New",
+ BLT_I18NCONTEXT_ID_SPEAKER,
+ BLT_I18NCONTEXT_ID_SOUND,
+ BLT_I18NCONTEXT_ID_ARMATURE,
+ BLT_I18NCONTEXT_ID_ACTION,
+ BLT_I18NCONTEXT_ID_NODETREE,
+ BLT_I18NCONTEXT_ID_BRUSH,
+ BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
+ BLT_I18NCONTEXT_ID_GPENCIL,
+ BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
+ BLT_I18NCONTEXT_ID_WORKSPACE,
+ BLT_I18NCONTEXT_ID_LIGHTPROBE,
+ );
+
+ if (newop) {
+ but = uiDefIconTextButO(
+ block, but_type, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN,
+ (id) ? "" : CTX_IFACE_(template_id_context(type), "New"), 0, 0, w, but_height, NULL);
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
+ }
+ else {
+ but = uiDefIconTextBut(
+ block, but_type, 0, ICON_ZOOMIN, (id) ? "" : CTX_IFACE_(template_id_context(type), "New"),
+ 0, 0, w, but_height, NULL, 0, 0, 0, 0, NULL);
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
+ }
+
+ if ((idfrom && idfrom->lib) || !editable) {
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+
+#ifndef WITH_INTERNATIONAL
+ UNUSED_VARS(type);
+#endif
+
+ return but;
+}
+
static void template_ID(
bContext *C, uiLayout *layout, TemplateID *template_ui, StructRNA *type, int flag,
const char *newop, const char *openop, const char *unlinkop)
@@ -484,6 +638,7 @@ static void template_ID(
// ListBase *lb; // UNUSED
ID *id, *idfrom;
const bool editable = RNA_property_editable(&template_ui->ptr, template_ui->prop);
+ const bool use_previews = template_ui->preview = (flag & UI_ID_PREVIEWS) != 0;
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
id = idptr.data;
@@ -496,32 +651,11 @@ static void template_ID(
if (idptr.type)
type = idptr.type;
- if (flag & UI_ID_PREVIEWS) {
- template_ui->preview = true;
-
- but = uiDefBlockButN(
- block, id_search_menu, MEM_dupallocN(template_ui), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6,
- TIP_(template_id_browse_tip(type)));
- ui_def_but_icon(
- but, id ? ui_id_icon_get(C, id, true) : RNA_struct_ui_icon(type),
- UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
-
- if ((idfrom && idfrom->lib) || !editable)
- UI_but_flag_enable(but, UI_BUT_DISABLED);
-
- uiLayoutRow(layout, true);
- }
- else if (flag & UI_ID_BROWSE) {
- but = uiDefBlockButN(
- block, id_search_menu, MEM_dupallocN(template_ui), "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y,
- TIP_(template_id_browse_tip(type)));
- ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON);
- /* default dragging of icon for id browse buttons */
- UI_but_drag_set_id(but, id);
- UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
-
- if ((idfrom && idfrom->lib) || !editable)
- UI_but_flag_enable(but, UI_BUT_DISABLED);
+ if (flag & UI_ID_BROWSE) {
+ template_add_button_search_menu(
+ C, layout, block, &template_ui->ptr, template_ui->prop,
+ id_search_menu, MEM_dupallocN(template_ui), TIP_(template_id_browse_tip(type)),
+ use_previews, editable);
}
/* text button with name */
@@ -532,7 +666,7 @@ static void template_ID(
//text_idbutton(id, name);
name[0] = '\0';
but = uiDefButR(
- block, UI_BTYPE_TEXT, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y,
+ block, UI_BTYPE_TEXT, 0, name, 0, 0, TEMPLATE_SEARCH_TEXTBUT_WIDTH, TEMPLATE_SEARCH_TEXTBUT_HEIGHT,
&idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type));
UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_RENAME));
if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT);
@@ -545,14 +679,28 @@ static void template_ID(
UI_but_flag_enable(but, UI_BUT_DISABLED);
}
else {
+ const bool disabled = (
+ !id_make_local(CTX_data_main(C), id, true /* test */, false) ||
+ (idfrom && idfrom->lib));
but = uiDefIconBut(
block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0, 0, 0, 0, TIP_("Direct linked library data-block, click to make local"));
- if (!id_make_local(CTX_data_main(C), id, true /* test */, false) || (idfrom && idfrom->lib))
+ NULL, 0, 0, 0, 0,
+ TIP_("Direct linked library data-block, click to make local, "
+ "Shift + Click to create a static override"));
+ if (disabled) {
UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+ else {
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_LOCAL));
+ }
}
-
- UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_LOCAL));
+ }
+ else if (ID_IS_STATIC_OVERRIDE(id)) {
+ but = uiDefIconBut(
+ block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_OVERRIDE, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ NULL, 0, 0, 0, 0,
+ TIP_("Static override of linked library data-block, click to make fully local"));
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_OVERRIDE));
}
if (id->us > 1) {
@@ -581,61 +729,13 @@ static void template_ID(
if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT);
- if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
+ if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) {
uiDefButR(block, UI_BTYPE_TOGGLE, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
}
}
if (flag & UI_ID_ADD_NEW) {
- int w = id ? UI_UNIT_X : (flag & UI_ID_OPEN) ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
-
- /* i18n markup, does nothing! */
- BLT_I18N_MSGID_MULTI_CTXT(
- "New",
- BLT_I18NCONTEXT_DEFAULT,
- BLT_I18NCONTEXT_ID_SCENE,
- BLT_I18NCONTEXT_ID_OBJECT,
- BLT_I18NCONTEXT_ID_MESH,
- BLT_I18NCONTEXT_ID_CURVE,
- BLT_I18NCONTEXT_ID_METABALL,
- BLT_I18NCONTEXT_ID_MATERIAL,
- BLT_I18NCONTEXT_ID_TEXTURE,
- BLT_I18NCONTEXT_ID_IMAGE,
- BLT_I18NCONTEXT_ID_LATTICE,
- BLT_I18NCONTEXT_ID_LAMP,
- BLT_I18NCONTEXT_ID_CAMERA,
- BLT_I18NCONTEXT_ID_WORLD,
- BLT_I18NCONTEXT_ID_SCREEN,
- BLT_I18NCONTEXT_ID_TEXT,
- );
- BLT_I18N_MSGID_MULTI_CTXT(
- "New",
- BLT_I18NCONTEXT_ID_SPEAKER,
- BLT_I18NCONTEXT_ID_SOUND,
- BLT_I18NCONTEXT_ID_ARMATURE,
- BLT_I18NCONTEXT_ID_ACTION,
- BLT_I18NCONTEXT_ID_NODETREE,
- BLT_I18NCONTEXT_ID_BRUSH,
- BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
- BLT_I18NCONTEXT_ID_GPENCIL,
- BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
- );
-
- if (newop) {
- but = uiDefIconTextButO(
- block, UI_BTYPE_BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN,
- (id) ? "" : CTX_IFACE_(template_id_context(type), "New"), 0, 0, w, UI_UNIT_Y, NULL);
- UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
- }
- else {
- but = uiDefIconTextBut(
- block, UI_BTYPE_BUT, 0, ICON_ZOOMIN, (id) ? "" : CTX_IFACE_(template_id_context(type), "New"),
- 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
- UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
- }
-
- if ((idfrom && idfrom->lib) || !editable)
- UI_but_flag_enable(but, UI_BUT_DISABLED);
+ template_id_def_new_but(block, id, template_ui, type, newop, editable, flag & UI_ID_OPEN, false, UI_UNIT_X);
}
/* Due to space limit in UI - skip the "open" icon for packed data, and allow to unpack.
@@ -708,9 +808,59 @@ static void template_ID(
UI_block_align_end(block);
}
+static void template_ID_tabs(
+ bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, int flag,
+ const char *newop, const char *UNUSED(openop), const char *unlinkop)
+{
+ const ARegion *region = CTX_wm_region(C);
+ const PointerRNA active_ptr = RNA_property_pointer_get(&template->ptr, template->prop);
+ const int but_align = (region->alignment == RGN_ALIGN_TOP) ? UI_BUT_ALIGN_DOWN : UI_BUT_ALIGN_TOP;
+ const int but_height = UI_UNIT_Y * 1.1;
+
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiStyle *style = UI_style_get_dpi();
+
+
+ for (ID *id = template->idlb->first; id; id = id->next) {
+ wmOperatorType *unlink_ot = WM_operatortype_find(unlinkop, false);
+ const bool is_active = active_ptr.data == id;
+ const unsigned int but_width = (
+ UI_fontstyle_string_width(&style->widgetlabel, id->name + 2) + UI_UNIT_X +
+ (is_active ? ICON_DEFAULT_WIDTH_SCALE : 0));
+ uiButTab *tab;
+
+ tab = (uiButTab *)uiDefButR_prop(
+ block, UI_BTYPE_TAB, 0, "", 0, 0, but_width, UI_UNIT_Y * 1.1,
+ &template->ptr, template->prop, 0, 0.0f,
+ sizeof(id->name) - 2, 0.0f, 0.0f, "");
+ UI_but_funcN_set(&tab->but, template_ID_set_property_cb, MEM_dupallocN(template), id);
+ tab->but.custom_data = (void *)id;
+ tab->unlink_ot = unlink_ot;
+
+ if (is_active) {
+ UI_but_flag_enable(&tab->but, UI_BUT_VALUE_CLEAR);
+ }
+ UI_but_drawflag_enable(&tab->but, but_align);
+ }
+
+ if (flag & UI_ID_ADD_NEW) {
+ const bool editable = RNA_property_editable(&template->ptr, template->prop);
+ uiBut *but;
+
+ if (active_ptr.type) {
+ type = active_ptr.type;
+ }
+
+ but = template_id_def_new_but(block, active_ptr.data, template, type, newop, editable, flag & UI_ID_OPEN, true, but_height);
+ UI_but_drawflag_enable(but, but_align);
+ }
+}
+
static void ui_template_id(
- uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
- const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols, int filter)
+ uiLayout *layout, bContext *C,
+ PointerRNA *ptr, const char *propname,
+ const char *newop, const char *openop, const char *unlinkop,
+ int flag, int prv_rows, int prv_cols, int filter, bool use_tabs)
{
TemplateID *template_ui;
PropertyRNA *prop;
@@ -751,8 +901,14 @@ static void ui_template_id(
* - template_ID makes a copy of the template data and assigns it to the relevant buttons
*/
if (template_ui->idlb) {
- uiLayoutRow(layout, true);
- template_ID(C, layout, template_ui, type, flag, newop, openop, unlinkop);
+ if (use_tabs) {
+ uiLayoutRow(layout, true);
+ template_ID_tabs(C, layout, template_ui, type, flag, newop, openop, unlinkop);
+ }
+ else {
+ uiLayoutRow(layout, true);
+ template_ID(C, layout, template_ui, type, flag, newop, openop, unlinkop);
+ }
}
MEM_freeN(template_ui);
@@ -763,15 +919,21 @@ void uiTemplateID(
const char *openop, const char *unlinkop, int filter)
{
ui_template_id(
- layout, C, ptr, propname, newop, openop, unlinkop,
- UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, 0, 0, filter);
+ layout, C, ptr, propname,
+ newop, openop, unlinkop,
+ UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE,
+ 0, 0, filter, false);
}
void uiTemplateIDBrowse(
uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
const char *openop, const char *unlinkop, int filter)
{
- ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME, 0, 0, filter);
+ ui_template_id(
+ layout, C, ptr, propname,
+ newop, openop, unlinkop,
+ UI_ID_BROWSE | UI_ID_RENAME,
+ 0, 0, filter, false);
}
void uiTemplateIDPreview(
@@ -779,8 +941,26 @@ void uiTemplateIDPreview(
const char *openop, const char *unlinkop, int rows, int cols, int filter)
{
ui_template_id(
- layout, C, ptr, propname, newop, openop, unlinkop,
- UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols, filter);
+ layout, C, ptr, propname,
+ newop, openop, unlinkop,
+ UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS,
+ rows, cols, filter, false);
+}
+
+/**
+ * Version of #uiTemplateID using tabs.
+ */
+void uiTemplateIDTabs(
+ uiLayout *layout, bContext *C,
+ PointerRNA *ptr, const char *propname,
+ const char *newop, const char *openop, const char *unlinkop,
+ int filter)
+{
+ ui_template_id(
+ layout, C, ptr, propname,
+ newop, openop, unlinkop,
+ UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE,
+ 0, 0, filter, true);
}
/************************ ID Chooser Template ***************************/
@@ -842,6 +1022,209 @@ void uiTemplateAnyID(
uiItemFullR(sub, ptr, propID, 0, 0, 0, "", ICON_NONE);
}
+/********************* Search Template ********************/
+
+typedef struct TemplateSearch {
+ uiRNACollectionSearch search_data;
+
+ bool use_previews;
+ int preview_rows, preview_cols;
+} TemplateSearch;
+
+static void template_search_handle_cb(bContext *C, void *arg_template, void *item)
+{
+ TemplateSearch *template_search = arg_template;
+ uiRNACollectionSearch *coll_search = &template_search->search_data;
+ StructRNA *type = RNA_property_pointer_type(&coll_search->target_ptr, coll_search->target_prop);
+ PointerRNA item_ptr;
+
+ RNA_pointer_create(NULL, type, item, &item_ptr);
+ RNA_property_pointer_set(&coll_search->target_ptr, coll_search->target_prop, item_ptr);
+ RNA_property_update(C, &coll_search->target_ptr, coll_search->target_prop);
+}
+
+static uiBlock *template_search_menu(bContext *C, ARegion *region, void *arg_template)
+{
+ static TemplateSearch template_search;
+ PointerRNA active_ptr;
+
+ /* arg_template is malloced, can be freed by parent button */
+ template_search = *((TemplateSearch *)arg_template);
+ active_ptr = RNA_property_pointer_get(
+ &template_search.search_data.target_ptr,
+ template_search.search_data.target_prop);
+
+ return template_common_search_menu(
+ C, region, ui_rna_collection_search_cb, &template_search,
+ template_search_handle_cb, active_ptr.data,
+ template_search.preview_rows, template_search.preview_cols);
+}
+
+static void template_search_add_button_searchmenu(
+ const bContext *C, uiLayout *layout, uiBlock *block,
+ TemplateSearch *template_search, const bool editable)
+{
+ const char *ui_description = RNA_property_ui_description(template_search->search_data.target_prop);
+
+ template_add_button_search_menu(
+ C, layout, block,
+ &template_search->search_data.target_ptr, template_search->search_data.target_prop,
+ template_search_menu, MEM_dupallocN(template_search), ui_description,
+ template_search->use_previews, editable);
+}
+
+static void template_search_add_button_name(
+ uiBlock *block, PointerRNA *active_ptr, const StructRNA *type)
+{
+ uiDefAutoButR(
+ block, active_ptr, RNA_struct_name_property(type), 0, "", ICON_NONE,
+ 0, 0, TEMPLATE_SEARCH_TEXTBUT_WIDTH, TEMPLATE_SEARCH_TEXTBUT_HEIGHT);
+}
+
+static void template_search_add_button_operator(
+ uiBlock *block, const char * const operator_name,
+ const int opcontext, const int icon, const bool editable)
+{
+ if (!operator_name) {
+ return;
+ }
+
+ uiBut *but = uiDefIconButO(
+ block, UI_BTYPE_BUT, operator_name, opcontext, icon,
+ 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+
+ if (!editable) {
+ UI_but_drawflag_enable(but, UI_BUT_DISABLED);
+ }
+}
+
+static void template_search_buttons(
+ const bContext *C, uiLayout *layout, TemplateSearch *template_search,
+ const char *newop, const char *unlinkop)
+{
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiRNACollectionSearch *search_data = &template_search->search_data;
+ StructRNA *type = RNA_property_pointer_type(&search_data->target_ptr, search_data->target_prop);
+ const bool editable = RNA_property_editable(&search_data->target_ptr, search_data->target_prop);
+ PointerRNA active_ptr = RNA_property_pointer_get(&search_data->target_ptr, search_data->target_prop);
+
+ if (active_ptr.type) {
+ /* can only get correct type when there is an active item */
+ type = active_ptr.type;
+ }
+
+ uiLayoutRow(layout, true);
+ UI_block_align_begin(block);
+
+ template_search_add_button_searchmenu(C, layout, block, template_search, editable);
+ template_search_add_button_name(block, &active_ptr, type);
+ template_search_add_button_operator(block, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, editable);
+ template_search_add_button_operator(block, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, editable);
+
+ UI_block_align_end(block);
+}
+
+static PropertyRNA *template_search_get_searchprop(
+ PointerRNA *targetptr, PropertyRNA *targetprop,
+ PointerRNA *searchptr, const char * const searchpropname)
+{
+ PropertyRNA *searchprop;
+
+ if (searchptr && !searchptr->data) {
+ searchptr = NULL;
+ }
+
+ if (!searchptr && !searchpropname) {
+ /* both NULL means we don't use a custom rna collection to search in */
+ }
+ else if (!searchptr && searchpropname) {
+ RNA_warning("searchpropname defined (%s) but searchptr is missing", searchpropname);
+ }
+ else if (searchptr && !searchpropname) {
+ RNA_warning("searchptr defined (%s) but searchpropname is missing", RNA_struct_identifier(searchptr->type));
+ }
+ else if (!(searchprop = RNA_struct_find_property(searchptr, searchpropname))) {
+ RNA_warning("search collection property not found: %s.%s",
+ RNA_struct_identifier(searchptr->type), searchpropname);
+ }
+ else if (RNA_property_type(searchprop) != PROP_COLLECTION) {
+ RNA_warning("search collection property is not a collection type: %s.%s",
+ RNA_struct_identifier(searchptr->type), searchpropname);
+ }
+ /* check if searchprop has same type as targetprop */
+ else if (RNA_property_pointer_type(searchptr, searchprop) != RNA_property_pointer_type(targetptr, targetprop)) {
+ RNA_warning("search collection items from %s.%s are not of type %s",
+ RNA_struct_identifier(searchptr->type), searchpropname,
+ RNA_struct_identifier(RNA_property_pointer_type(targetptr, targetprop)));
+ }
+ else {
+ return searchprop;
+ }
+
+ return NULL;
+}
+
+static TemplateSearch *template_search_setup(
+ PointerRNA *ptr, const char * const propname,
+ PointerRNA *searchptr, const char * const searchpropname)
+{
+ TemplateSearch *template_search;
+ PropertyRNA *prop, *searchprop;
+
+ prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop || RNA_property_type(prop) != PROP_POINTER) {
+ RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return NULL;
+ }
+ searchprop = template_search_get_searchprop(ptr, prop, searchptr, searchpropname);
+
+ template_search = MEM_callocN(sizeof(*template_search), __func__);
+ template_search->search_data.target_ptr = *ptr;
+ template_search->search_data.target_prop = prop;
+ template_search->search_data.search_ptr = *searchptr;
+ template_search->search_data.search_prop = searchprop;
+
+ return template_search;
+}
+
+/**
+ * Search menu to pick an item from a collection.
+ * A version of uiTemplateID that works for non-ID types.
+ */
+void uiTemplateSearch(
+ uiLayout *layout, bContext *C,
+ PointerRNA *ptr, const char *propname,
+ PointerRNA *searchptr, const char *searchpropname,
+ const char *newop, const char *unlinkop)
+{
+ TemplateSearch *template_search = template_search_setup(ptr, propname, searchptr, searchpropname);
+ if (template_search != NULL) {
+ template_search_buttons(C, layout, template_search, newop, unlinkop);
+ MEM_freeN(template_search);
+ }
+}
+
+void uiTemplateSearchPreview(
+ uiLayout *layout, bContext *C,
+ PointerRNA *ptr, const char *propname,
+ PointerRNA *searchptr, const char *searchpropname,
+ const char *newop, const char *unlinkop,
+ const int rows, const int cols)
+{
+ TemplateSearch *template_search = template_search_setup(ptr, propname, searchptr, searchpropname);
+
+ if (template_search != NULL) {
+ template_search->use_previews = true;
+ template_search->preview_rows = rows;
+ template_search->preview_cols = cols;
+
+ template_search_buttons(C, layout, template_search, newop, unlinkop);
+
+ MEM_freeN(template_search);
+ }
+}
+
/********************* RNA Path Builder Template ********************/
/* ---------- */
@@ -896,7 +1279,7 @@ static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
ob->partype = PAROBJECT;
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
ED_undo_push(C, "Modifier convert to real");
}
@@ -979,8 +1362,7 @@ static uiLayout *draw_modifier(
UI_block_emboss_set(block, UI_EMBOSS);
/* modifier name */
- md->scene = scene;
- if (mti->isDisabled && mti->isDisabled(md, 0)) {
+ if (mti->isDisabled && mti->isDisabled(scene, md, 0)) {
uiLayoutSetRedAlert(row, true);
}
uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
@@ -1041,8 +1423,7 @@ static uiLayout *draw_modifier(
UI_block_emboss_set(block, UI_EMBOSS_NONE);
/* When Modifier is a simulation, show button to switch to context rather than the delete button. */
if (modifier_can_delete(md) &&
- (!modifier_is_simulation(md) ||
- STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME)))
+ !modifier_is_simulation(md))
{
uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove");
}
@@ -1080,13 +1461,15 @@ static uiLayout *draw_modifier(
}
else {
uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
- uiItemEnumO(row, "OBJECT_OT_modifier_apply", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
- 0, "apply_as", MODIFIER_APPLY_DATA);
+ uiItemEnumO(
+ row, "OBJECT_OT_modifier_apply", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
+ 0, "apply_as", MODIFIER_APPLY_DATA);
if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) {
- uiItemEnumO(row, "OBJECT_OT_modifier_apply",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"),
- 0, "apply_as", MODIFIER_APPLY_SHAPE);
+ uiItemEnumO(
+ row, "OBJECT_OT_modifier_apply",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"),
+ 0, "apply_as", MODIFIER_APPLY_SHAPE);
}
}
@@ -1156,6 +1539,74 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
return NULL;
}
+
+/************************ Redo Buttons Template *************************/
+
+static bool template_operator_redo_property_buts_poll(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+{
+ return (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED) == 0;
+}
+
+static void template_operator_redo_property_buts_draw(
+ const bContext *C, wmOperator *op,
+ uiLayout *layout, int layout_flags,
+ bool *r_has_advanced)
+{
+ if (op->type->flag & OPTYPE_MACRO) {
+ for (wmOperator *macro_op = op->macro.first; macro_op; macro_op = macro_op->next) {
+ template_operator_redo_property_buts_draw(C, macro_op, layout, layout_flags, r_has_advanced);
+ }
+ }
+ else {
+ /* Might want to make label_align adjustable somehow. */
+ eAutoPropButsReturn return_info = uiTemplateOperatorPropertyButs(
+ C, layout, op, r_has_advanced ? template_operator_redo_property_buts_poll : NULL,
+ UI_BUT_LABEL_ALIGN_NONE, layout_flags);
+ if (return_info & UI_PROP_BUTS_ANY_FAILED_CHECK) {
+ if (r_has_advanced) {
+ *r_has_advanced = true;
+ }
+ }
+ }
+}
+
+void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C)
+{
+ wmOperator *op = WM_operator_last_redo(C);
+ uiBlock *block = uiLayoutGetBlock(layout);
+
+ if (op == NULL) {
+ return;
+ }
+
+ /* Disable for now, doesn't fit well in popover. */
+#if 0
+ /* Repeat button with operator name as text. */
+ uiItemFullO(layout, "SCREEN_OT_repeat_last", RNA_struct_ui_name(op->type->srna),
+ ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL);
+#endif
+
+ if (WM_operator_repeat_check(C, op)) {
+ int layout_flags = 0;
+ if (block->panel == NULL) {
+ layout_flags = UI_TEMPLATE_OP_PROPS_SHOW_TITLE;
+ }
+#if 0
+ bool has_advanced = false;
+#endif
+
+ UI_block_func_set(block, ED_undo_operator_repeat_cb, op, NULL);
+ template_operator_redo_property_buts_draw(C, op, layout, layout_flags, NULL /* &has_advanced */ );
+ UI_block_func_set(block, NULL, NULL, NULL); /* may want to reset to old state instead of NULLing all */
+
+#if 0
+ if (has_advanced) {
+ uiItemO(layout, IFACE_("More..."), ICON_NONE, "SCREEN_OT_redo_last");
+ }
+#endif
+ }
+}
+
/************************ Constraint Template *************************/
#include "DNA_constraint_types.h"
@@ -1179,7 +1630,7 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event)
Main *bmain = CTX_data_main(C);
if (ob->pose)
BKE_pose_tag_recalc(bmain, ob->pose); /* checks & sorts pose channels */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
break;
}
#endif
@@ -1193,8 +1644,8 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event)
* object_test_constraints(ob);
* if (ob->pose) BKE_pose_update_constraint_flags(ob->pose); */
- if (ob->type == OB_ARMATURE) DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
- else DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ if (ob->type == OB_ARMATURE) DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
+ else DEG_id_tag_update(&ob->id, OB_RECALC_OB);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
}
@@ -1305,7 +1756,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
/* enabled */
UI_block_emboss_set(block, UI_EMBOSS_NONE);
uiItemR(row, &ptr, "mute", 0, "",
- (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF);
+ (con->flag & CONSTRAINT_OFF) ? ICON_HIDE_ON : ICON_HIDE_OFF);
UI_block_emboss_set(block, UI_EMBOSS);
uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
@@ -1415,7 +1866,7 @@ void uiTemplatePreview(
char _preview_id[UI_MAX_NAME_STR];
if (id && !ELEM(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA, ID_LS)) {
- RNA_warning("Expected ID of type material, texture, lamp, world or line style");
+ RNA_warning("Expected ID of type material, texture, light, world or line style");
return;
}
@@ -1506,7 +1957,7 @@ void uiTemplatePreview(
pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
}
else if (GS(parent->name) == ID_LA) {
- uiDefButS(block, UI_BTYPE_ROW, B_MATPRV, IFACE_("Lamp"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ uiDefButS(block, UI_BTYPE_ROW, B_MATPRV, IFACE_("Light"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
}
else if (GS(parent->name) == ID_WO) {
@@ -1746,6 +2197,19 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname
MEM_freeN(cb);
}
+/********************* Icon Template ************************/
+/**
+ * \param icon_scale: Scale of the icon, 1x == button height.
+ */
+void uiTemplateIcon(uiLayout *layout, int icon_value, float icon_scale)
+{
+ uiBlock *block;
+ uiBut *but;
+
+ block = uiLayoutAbsoluteBlock(layout);
+ but = uiDefIconBut(block, UI_BTYPE_LABEL, 0, ICON_X, 0, 0, UI_UNIT_X * icon_scale, UI_UNIT_Y * icon_scale, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ ui_def_but_icon(but, icon_value, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
+}
/********************* Icon viewer Template ************************/
typedef struct IconViewMenuArgs {
@@ -1832,13 +2296,20 @@ void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname,
value = RNA_property_enum_get(ptr, prop);
RNA_enum_icon_from_value(items, value, &icon);
- cb_args = MEM_callocN(sizeof(IconViewMenuArgs), __func__);
- cb_args->ptr = *ptr;
- cb_args->prop = prop;
- cb_args->show_labels = show_labels;
- cb_args->icon_scale = icon_scale;
- but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb_args, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, "");
+ if (RNA_property_editable(ptr, prop)) {
+ cb_args = MEM_callocN(sizeof(IconViewMenuArgs), __func__);
+ cb_args->ptr = *ptr;
+ cb_args->prop = prop;
+ cb_args->show_labels = show_labels;
+ cb_args->icon_scale = icon_scale;
+
+ but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb_args, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, "");
+ }
+ else {
+ but = uiDefIconBut(block, UI_BTYPE_LABEL, 0, ICON_X, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ }
+
ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
@@ -2669,78 +3140,6 @@ void uiTemplateLayers(
}
}
-void uiTemplateGameStates(
- uiLayout *layout, PointerRNA *ptr, const char *propname,
- PointerRNA *used_ptr, const char *used_propname, int active_state)
-{
- uiLayout *uRow, *uCol;
- PropertyRNA *prop, *used_prop = NULL;
- int groups, cols, states;
- int group, col, state, row;
- int cols_per_group = 5;
- Object *ob = (Object *)ptr->id.data;
-
- prop = RNA_struct_find_property(ptr, propname);
- if (!prop) {
- RNA_warning("states property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
- return;
- }
-
- /* the number of states determines the way we group them
- * - we want 2 rows only (for now)
- * - the number of columns (cols) is the total number of buttons per row
- * the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be
- * - for now, only split into groups if group will have at least 5 items
- */
- states = RNA_property_array_length(ptr, prop);
- cols = (states / 2) + (states % 2);
- groups = ((cols / 2) < cols_per_group) ? (1) : (cols / cols_per_group);
-
- if (used_ptr && used_propname) {
- used_prop = RNA_struct_find_property(used_ptr, used_propname);
- if (!used_prop) {
- RNA_warning("used layers property not found: %s.%s", RNA_struct_identifier(ptr->type), used_propname);
- return;
- }
-
- if (RNA_property_array_length(used_ptr, used_prop) < states)
- used_prop = NULL;
- }
-
- /* layers are laid out going across rows, with the columns being divided into groups */
-
- for (group = 0; group < groups; group++) {
- uCol = uiLayoutColumn(layout, true);
-
- for (row = 0; row < 2; row++) {
- uiBlock *block;
- uiBut *but;
-
- uRow = uiLayoutRow(uCol, true);
- block = uiLayoutGetBlock(uRow);
- state = groups * cols_per_group * row + cols_per_group * group;
-
- /* add layers as toggle buts */
- for (col = 0; (col < cols_per_group) && (state < states); col++, state++) {
- int icon = 0;
- int butlay = 1 << state;
-
- if (active_state & butlay)
- icon = ICON_LAYER_ACTIVE;
- else if (used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, state))
- icon = ICON_LAYER_USED;
-
- but = uiDefIconButR_prop(
- block, UI_BTYPE_ICON_TOGGLE, 0, icon, 0, 0, UI_UNIT_X / 2, UI_UNIT_Y / 2, ptr, prop,
- state, 0, 0, -1, -1, sca_state_name_get(ob, state));
- UI_but_func_set(but, handle_layer_buttons, but, SET_INT_IN_POINTER(state));
- but->type = UI_BTYPE_TOGGLE;
- }
- }
- }
-}
-
-
/************************* List Template **************************/
static void uilist_draw_item_default(
struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout,
@@ -3535,11 +3934,14 @@ static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), void *op_pt,
* Draw Operator property buttons for redoing execution with different settings.
* This function does not initialize the layout, functions can be called on the layout before and after.
*/
-void uiTemplateOperatorPropertyButs(
+eAutoPropButsReturn uiTemplateOperatorPropertyButs(
const bContext *C, uiLayout *layout, wmOperator *op,
bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *),
- const char label_align, const short flag)
+ const eButLabelAlign label_align, const short flag)
{
+ uiBlock *block = uiLayoutGetBlock(layout);
+ eAutoPropButsReturn return_info = 0;
+
if (!op->properties) {
IDPropertyTemplate val = {0};
op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
@@ -3552,14 +3954,14 @@ void uiTemplateOperatorPropertyButs(
/* poll() on this operator may still fail, at the moment there is no nice feedback when this happens
* just fails silently */
if (!WM_operator_repeat_check(C, op)) {
- UI_block_lock_set(uiLayoutGetBlock(layout), true, "Operator can't' redo");
+ UI_block_lock_set(block, true, "Operator can't' redo");
/* XXX, could give some nicer feedback or not show redo panel at all? */
uiItemL(layout, IFACE_("* Redo Unsupported *"), ICON_NONE);
}
else {
/* useful for macros where only one of the steps can't be re-done */
- UI_block_lock_clear(uiLayoutGetBlock(layout));
+ UI_block_lock_clear(block);
}
/* menu */
@@ -3568,7 +3970,7 @@ void uiTemplateOperatorPropertyButs(
PointerRNA op_ptr;
uiLayout *row;
- uiLayoutGetBlock(layout)->ui_operator = op;
+ block->ui_operator = op;
row = uiLayoutRow(layout, true);
uiItemM(row, "WM_MT_operator_presets", NULL, ICON_NONE);
@@ -3587,19 +3989,21 @@ void uiTemplateOperatorPropertyButs(
op->type->ui((bContext *)C, op);
op->layout = NULL;
- /* UI_LAYOUT_OP_SHOW_EMPTY ignored */
+ /* UI_LAYOUT_OP_SHOW_EMPTY ignored. return_info is ignored too. We could
+ * allow ot.ui callback to return this, but not needed right now. */
}
else {
wmWindowManager *wm = CTX_wm_manager(C);
PointerRNA ptr;
- int empty;
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+ uiLayoutSetPropSep(layout, true);
+
/* main draw call */
- empty = uiDefAutoButsRNA(layout, &ptr, check_prop, label_align) == 0;
+ return_info = uiDefAutoButsRNA(layout, &ptr, check_prop, label_align, (flag & UI_TEMPLATE_OP_PROPS_COMPACT));
- if (empty && (flag & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) {
+ if ((return_info & UI_PROP_BUTS_NONE_ADDED) && (flag & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) {
uiItemL(layout, IFACE_("No Properties"), ICON_NONE);
}
}
@@ -3609,7 +4013,6 @@ void uiTemplateOperatorPropertyButs(
* but this is not so important if this button is drawn in those cases
* (which isn't all that likely anyway) - campbell */
if (op->properties->len) {
- uiBlock *block;
uiBut *but;
uiLayout *col; /* needed to avoid alignment errors with previous buttons */
@@ -3622,8 +4025,9 @@ void uiTemplateOperatorPropertyButs(
#endif
/* set various special settings for buttons */
- {
- uiBlock *block = uiLayoutGetBlock(layout);
+
+ /* Only do this if we're not refreshing an existing UI. */
+ if (block->oldblock == NULL) {
const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0;
uiBut *but;
@@ -3643,6 +4047,8 @@ void uiTemplateOperatorPropertyButs(
}
}
}
+
+ return return_info;
}
/************************* Running Jobs Template **************************/
@@ -3882,18 +4288,18 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
/* make a box around the report to make it stand out */
UI_block_align_begin(block);
- but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", 0, 0, UI_UNIT_X + 10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
+ but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", 0, 0, UI_UNIT_X + 5, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
/* set the report's bg color in but->col - UI_BTYPE_ROUNDBOX feature */
rgb_float_to_uchar(but->col, rti->col);
but->col[3] = 255;
- but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y,
+ but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", UI_UNIT_X + 5, 0, UI_UNIT_X + width, UI_UNIT_Y,
NULL, 0.0f, 0.0f, 0, 0, "");
- but->col[0] = but->col[1] = but->col[2] = unit_float_to_uchar_clamp(rti->grayscale);
- but->col[3] = 255;
UI_block_align_end(block);
+ UI_GetThemeColorShade3ubv(TH_BACK, 20, but->col);
+ but->col[3] = 255;
/* icon and report message on top */
icon = UI_icon_from_report_type(report->type);
@@ -3911,10 +4317,50 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
UI_block_emboss_set(block, UI_EMBOSS);
- uiDefBut(block, UI_BTYPE_LABEL, 0, report->message, UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y,
+ uiDefBut(block, UI_BTYPE_LABEL, 0, report->message, UI_UNIT_X + 5, 0, UI_UNIT_X + width, UI_UNIT_Y,
NULL, 0.0f, 0.0f, 0, 0, "");
}
+
+void uiTemplateInputStatus(uiLayout *layout, struct bContext *C)
+{
+ wmWindow *win = CTX_wm_window(C);
+ WorkSpace *workspace = CTX_wm_workspace(C);
+
+ /* Workspace status text has priority. */
+ if (workspace->status_text) {
+ uiItemL(layout, workspace->status_text, ICON_NONE);
+ return;
+ }
+
+ if (WM_window_modal_keymap_status_draw(C, win, layout)) {
+ return;
+ }
+
+ /* Otherwise should cursor keymap status. */
+ for (int i = 0; i < 3; i++) {
+ uiLayout *box = uiLayoutRow(layout, false);
+ uiLayout *col = uiLayoutColumn(box, false);
+ uiLayout *row = uiLayoutRow(col, true);
+ uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
+
+ const char *msg = WM_window_cursor_keymap_status_get(win, i, 0);
+ const char *msg_drag = WM_window_cursor_keymap_status_get(win, i, 1);
+
+ if (msg || (msg_drag == NULL)) {
+ uiItemL(row, msg ? msg : "", (ICON_MOUSE_LMB + i));
+ }
+
+ if (msg_drag) {
+ uiItemL(row, msg_drag, (ICON_MOUSE_LMB_DRAG + i));
+ }
+
+ /* Use trick with empty string to keep icons in same position. */
+ row = uiLayoutRow(col, false);
+ uiItemL(row, " ", ICON_NONE);
+ }
+}
+
/********************************* Keymap *************************************/
static void keymap_item_modified(bContext *UNUSED(C), void *kmi_p, void *UNUSED(unused))
@@ -3977,6 +4423,7 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr)
if (propptr.data) {
uiBut *but = uiLayoutGetBlock(layout)->buttons.last;
+ WM_operator_properties_sanitize(&propptr, false);
template_keymap_item_properties(layout, NULL, &propptr);
/* attach callbacks to compensate for missing properties update,
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 1aa6f045266..d080397c488 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -157,66 +157,159 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
* \a check_prop callback filters functions to avoid drawing certain properties,
* in cases where PROP_HIDDEN flag can't be used for a property.
*/
-int uiDefAutoButsRNA(
+eAutoPropButsReturn uiDefAutoButsRNA(
uiLayout *layout, PointerRNA *ptr,
bool (*check_prop)(PointerRNA *, PropertyRNA *),
- const char label_align)
+ const eButLabelAlign label_align, const bool compact)
{
+ eAutoPropButsReturn return_info = UI_PROP_BUTS_NONE_ADDED;
uiLayout *split, *col;
int flag;
const char *name;
- int tot = 0;
-
- assert(ELEM(label_align, '\0', 'H', 'V'));
RNA_STRUCT_BEGIN (ptr, prop)
{
flag = RNA_property_flag(prop);
- if (flag & PROP_HIDDEN || (check_prop && check_prop(ptr, prop) == 0))
+
+ if (flag & PROP_HIDDEN) {
+ continue;
+ }
+ if (check_prop && check_prop(ptr, prop) == 0) {
+ return_info |= UI_PROP_BUTS_ANY_FAILED_CHECK;
continue;
+ }
- if (label_align != '\0') {
- PropertyType type = RNA_property_type(prop);
- const bool is_boolean = (type == PROP_BOOLEAN && !RNA_property_array_check(prop));
+ switch (label_align) {
+ case UI_BUT_LABEL_ALIGN_COLUMN:
+ case UI_BUT_LABEL_ALIGN_SPLIT_COLUMN:
+ {
+ PropertyType type = RNA_property_type(prop);
+ const bool is_boolean = (type == PROP_BOOLEAN && !RNA_property_array_check(prop));
- name = RNA_property_ui_name(prop);
+ name = RNA_property_ui_name(prop);
- if (label_align == 'V') {
- col = uiLayoutColumn(layout, true);
+ if (label_align == UI_BUT_LABEL_ALIGN_COLUMN) {
+ col = uiLayoutColumn(layout, true);
- if (!is_boolean)
- uiItemL(col, name, ICON_NONE);
- }
- else { /* (label_align == 'H') */
- BLI_assert(label_align == 'H');
- split = uiLayoutSplit(layout, 0.5f, false);
+ if (!is_boolean)
+ uiItemL(col, name, ICON_NONE);
+ }
+ else {
+ BLI_assert(label_align == UI_BUT_LABEL_ALIGN_SPLIT_COLUMN);
+ split = uiLayoutSplit(layout, 0.5f, false);
+
+ col = uiLayoutColumn(split, false);
+ uiItemL(col, (is_boolean) ? "" : name, ICON_NONE);
+ col = uiLayoutColumn(split, false);
+ }
+
+ /* may meed to add more cases here.
+ * don't override enum flag names */
- col = uiLayoutColumn(split, false);
- uiItemL(col, (is_boolean) ? "" : name, ICON_NONE);
- col = uiLayoutColumn(split, false);
+ /* name is shown above, empty name for button below */
+ name = (flag & PROP_ENUM_FLAG || is_boolean) ? NULL : "";
+
+ break;
}
+ case UI_BUT_LABEL_ALIGN_NONE:
+ default:
+ col = layout;
+ name = NULL; /* no smart label alignment, show default name with button */
+ break;
+ }
+
+ uiItemFullR(col, ptr, prop, -1, 0, compact ? UI_ITEM_R_COMPACT : 0, name, ICON_NONE);
+ return_info &= ~UI_PROP_BUTS_NONE_ADDED;
+ }
+ RNA_STRUCT_END;
- /* may meed to add more cases here.
- * don't override enum flag names */
+ return return_info;
+}
+
+/* *** RNA collection search menu *** */
+
+typedef struct CollItemSearch {
+ struct CollItemSearch *next, *prev;
+ void *data;
+ char *name;
+ int index;
+ int iconid;
+} CollItemSearch;
+
+static int sort_search_items_list(const void *a, const void *b)
+{
+ const CollItemSearch *cis1 = a;
+ const CollItemSearch *cis2 = b;
- /* name is shown above, empty name for button below */
- name = (flag & PROP_ENUM_FLAG || is_boolean) ? NULL : "";
+ if (BLI_strcasecmp(cis1->name, cis2->name) > 0)
+ return 1;
+ else
+ return 0;
+}
+
+void ui_rna_collection_search_cb(const struct bContext *C, void *arg, const char *str, uiSearchItems *items)
+{
+ uiRNACollectionSearch *data = arg;
+ char *name;
+ int i = 0, iconid = 0, flag = RNA_property_flag(data->target_prop);
+ ListBase *items_list = MEM_callocN(sizeof(ListBase), "items_list");
+ CollItemSearch *cis;
+ const bool skip_filter = !(data->but_changed && *data->but_changed);
+
+ /* build a temporary list of relevant items first */
+ RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop)
+ {
+
+ if (flag & PROP_ID_SELF_CHECK)
+ if (itemptr.data == data->target_ptr.id.data)
+ continue;
+
+ /* use filter */
+ if (RNA_property_type(data->target_prop) == PROP_POINTER) {
+ if (RNA_property_pointer_poll(&data->target_ptr, data->target_prop, &itemptr) == 0)
+ continue;
}
- else {
- col = layout;
- name = NULL; /* no smart label alignment, show default name with button */
+
+ name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); /* could use the string length here */
+ iconid = 0;
+ if (itemptr.type && RNA_struct_is_ID(itemptr.type)) {
+ iconid = ui_id_icon_get(C, itemptr.data, false);
+ }
+
+ if (name) {
+ if (skip_filter || BLI_strcasestr(name, str)) {
+ cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch");
+ cis->data = itemptr.data;
+ cis->name = MEM_dupallocN(name);
+ cis->index = i;
+ cis->iconid = iconid;
+ BLI_addtail(items_list, cis);
+ }
+ MEM_freeN(name);
}
- uiItemFullR(col, ptr, prop, -1, 0, 0, name, ICON_NONE);
- tot++;
+ i++;
+ }
+ RNA_PROP_END;
+
+ BLI_listbase_sort(items_list, sort_search_items_list);
+
+ /* add search items from temporary list */
+ for (cis = items_list->first; cis; cis = cis->next) {
+ if (UI_search_item_add(items, cis->name, cis->data, cis->iconid) == false) {
+ break;
+ }
}
- RNA_STRUCT_END;
- return tot;
+ for (cis = items_list->first; cis; cis = cis->next) {
+ MEM_freeN(cis->name);
+ }
+ BLI_freelistN(items_list);
+ MEM_freeN(items_list);
}
-/***************************** ID Utilities *******************************/
+/***************************** ID Utilities *******************************/
int UI_icon_from_id(ID *id)
{
Object *ob;
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index a7de70629d1..03ff6593c59 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -43,13 +43,9 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_curve.h"
#include "RNA_access.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
#include "BLF_api.h"
#include "UI_interface.h"
@@ -58,6 +54,11 @@
#include "interface_intern.h"
#include "GPU_basic_shader.h"
+#include "GPU_batch.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
#ifdef WITH_INPUT_IME
# include "WM_types.h"
@@ -72,13 +73,19 @@ enum {
/* Show that holding the button opens a menu. */
UI_STATE_HOLD_ACTION = UI_BUT_UPDATE_DELAY,
UI_STATE_TEXT_INPUT = UI_BUT_UNDO,
+ UI_STATE_ACTIVE_LEFT = UI_BUT_VALUE_CLEAR,
+ UI_STATE_ACTIVE_RIGHT = UI_BUT_TEXTEDIT_UPDATE,
- UI_STATE_FLAGS_ALL = (UI_STATE_HOLD_ACTION | UI_STATE_TEXT_INPUT),
+ UI_STATE_FLAGS_ALL = (UI_STATE_HOLD_ACTION |
+ UI_STATE_TEXT_INPUT |
+ UI_STATE_ACTIVE_LEFT |
+ UI_STATE_ACTIVE_RIGHT),
};
/* Prevent accidental use. */
#define UI_BUT_UPDATE_DELAY ((void)0)
#define UI_BUT_UNDO ((void)0)
+
/* ************** widget base functions ************** */
/**
* - in: roundbox codes for corner types and radius
@@ -98,6 +105,8 @@ enum {
typedef struct uiWidgetTrias {
unsigned int tot;
+ int type;
+ float size, center[2];
float vec[16][2];
const unsigned int (*index)[3];
@@ -105,21 +114,24 @@ typedef struct uiWidgetTrias {
} uiWidgetTrias;
/* max as used by round_box__edges */
+/* Make sure to change widget_base_vert.glsl accordingly. */
#define WIDGET_CURVE_RESOLU 9
#define WIDGET_SIZE_MAX (WIDGET_CURVE_RESOLU * 4)
typedef struct uiWidgetBase {
-
+ /* TODO remove these completely */
int totvert, halfwayvert;
float outer_v[WIDGET_SIZE_MAX][2];
float inner_v[WIDGET_SIZE_MAX][2];
float inner_uv[WIDGET_SIZE_MAX][2];
- bool draw_inner, draw_outline, draw_emboss, draw_shadedir;
+ bool draw_inner, draw_outline, draw_emboss;
uiWidgetTrias tria1;
uiWidgetTrias tria2;
+ /* Widget shader parameters, must match the shader layout. */
+ uiWidgetBaseParameters uniform_params;
} uiWidgetBase;
/** uiWidgetType: for time being only for visual appearance,
@@ -150,13 +162,15 @@ static const float cornervec[WIDGET_CURVE_RESOLU][2] = {
{0.924, 0.617}, {0.98, 0.805}, {1.0, 1.0}
};
-#define WIDGET_AA_JITTER 8
-static const float jit[WIDGET_AA_JITTER][2] = {
+
+const float ui_pixel_jitter[UI_PIXEL_AA_JITTER][2] = {
{ 0.468813, -0.481430}, {-0.155755, -0.352820},
{ 0.219306, -0.238501}, {-0.393286, -0.110949},
{-0.024699, 0.013908}, { 0.343805, 0.147431},
{-0.272855, 0.269918}, { 0.095909, 0.388710}
};
+#define WIDGET_AA_JITTER UI_PIXEL_AA_JITTER
+#define jit ui_pixel_jitter
/* -------------------------------------------------------------------- */
/** \name Shape Preset Data
@@ -195,8 +209,8 @@ static const uint g_shape_preset_checkmark_face[4][3] = {
{3, 2, 4}, {3, 4, 5}, {1, 0, 3}, {0, 2, 3}
};
-#define OY -0.2
-#define SC 0.35
+#define OY (-0.2 / 2)
+#define SC (0.35 * 2)
static const float g_shape_preset_hold_action_vert[6][2] = {
{-0.5 + SC, 1.0 + OY}, {0.5, 1.0 + OY}, {0.5, 0.0 + OY + SC},
};
@@ -206,53 +220,364 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}}
/** \} */
+/* **************** Batch creations ****************** */
+/**
+ * In order to speed up UI drawing we create some batches that are then
+ * modified by specialized shaders to draw certain elements really fast.
+ * TODO: find a better place. Maybe it's own file?
+ **/
+
+/* offset in triavec[] in shader per type */
+static const int tria_ofs[ROUNDBOX_TRIA_MAX] = {
+ [ROUNDBOX_TRIA_NONE] = 0,
+ [ROUNDBOX_TRIA_ARROWS] = 0,
+ [ROUNDBOX_TRIA_SCROLL] = 12,
+ [ROUNDBOX_TRIA_MENU] = 28,
+ [ROUNDBOX_TRIA_CHECK] = 34,
+ [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 40,
+};
+static const int tria_vcount[ROUNDBOX_TRIA_MAX] = {
+ [ROUNDBOX_TRIA_NONE] = 0,
+ [ROUNDBOX_TRIA_ARROWS] = 6,
+ [ROUNDBOX_TRIA_SCROLL] = 16,
+ [ROUNDBOX_TRIA_MENU] = 6,
+ [ROUNDBOX_TRIA_CHECK] = 6,
+ [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 3,
+};
+
+static struct {
+ Gwn_Batch *roundbox_widget[ROUNDBOX_TRIA_MAX];
+
+ Gwn_Batch *roundbox_simple;
+ Gwn_Batch *roundbox_simple_aa;
+ Gwn_Batch *roundbox_simple_outline;
+ Gwn_Batch *roundbox_shadow;
+
+ Gwn_VertFormat format;
+ uint vflag_id;
+} g_ui_batch_cache = {{0}};
+
+static Gwn_VertFormat *vflag_format(void)
+{
+ if (g_ui_batch_cache.format.attr_len == 0) {
+ Gwn_VertFormat *format = &g_ui_batch_cache.format;
+ g_ui_batch_cache.vflag_id = GWN_vertformat_attr_add(format, "vflag", GWN_COMP_U32, 1, GWN_FETCH_INT);
+ }
+ return &g_ui_batch_cache.format;
+}
+
+#define INNER 0
+#define OUTLINE 1
+#define EMBOSS 2
+#define NO_AA WIDGET_AA_JITTER
+
+static void set_roundbox_vertex_data(
+ Gwn_VertBufRaw *vflag_step, uint32_t d)
+{
+ uint32_t *data = GWN_vertbuf_raw_step(vflag_step);
+ *data = d;
+}
+
+static uint32_t set_roundbox_vertex(
+ Gwn_VertBufRaw *vflag_step,
+ int corner_id, int corner_v, int jit_v, bool inner, bool emboss, int color)
+{
+ uint32_t *data = GWN_vertbuf_raw_step(vflag_step);
+ *data = corner_id;
+ *data |= corner_v << 2;
+ *data |= jit_v << 6;
+ *data |= color << 12;
+ *data |= (inner) ? (1 << 10) : 0; /* is inner vert */
+ *data |= (emboss) ? (1 << 11) : 0; /* is emboss vert */
+ return *data;
+}
+
+static uint32_t set_tria_vertex(
+ Gwn_VertBufRaw *vflag_step,
+ int tria_type, int tria_v, int tria_id, int jit_v)
+{
+ uint32_t *data = GWN_vertbuf_raw_step(vflag_step);
+ if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS)) {
+ tria_v += tria_id * tria_vcount[ROUNDBOX_TRIA_ARROWS];
+ }
+ *data = tria_ofs[tria_type] + tria_v;
+ *data |= jit_v << 6;
+ *data |= (tria_id == 0) ? (1 << 10) : 0; /* is first tria */
+ *data |= 1 << 14; /* is tria vert */
+ return *data;
+}
+
+static void roundbox_batch_add_tria(Gwn_VertBufRaw *vflag_step, int tria, uint32_t last_data)
+{
+ const int tria_num = ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU) ? 1 : 2;
+ /* for each tria */
+ for (int t = 0; t < tria_num; ++t) {
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ /* restart */
+ set_roundbox_vertex_data(vflag_step, last_data);
+ set_tria_vertex(vflag_step, tria, 0, t, j);
+ for (int v = 0; v < tria_vcount[tria]; v++) {
+ last_data = set_tria_vertex(vflag_step, tria, v, t, j);
+ }
+ }
+ }
+}
+
+Gwn_Batch *ui_batch_roundbox_widget_get(int tria)
+{
+ if (g_ui_batch_cache.roundbox_widget[tria] == NULL) {
+ uint32_t last_data;
+ Gwn_VertBufRaw vflag_step;
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format());
+ int vcount = WIDGET_SIZE_MAX; /* inner */
+ vcount += 2; /* restart */
+ vcount += ((WIDGET_SIZE_MAX + 1) * 2) * WIDGET_AA_JITTER; /* outline (edges) */
+ vcount += 2; /* restart */
+ vcount += ((WIDGET_CURVE_RESOLU * 2) * 2) * WIDGET_AA_JITTER; /* emboss */
+ if (tria) {
+ vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria1 */
+ if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU)) {
+ vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria2 */
+ }
+ }
+ GWN_vertbuf_data_alloc(vbo, vcount);
+ GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+ /* Inner */
+ for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
+ for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) {
+ last_data = set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER);
+ last_data = set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER);
+ }
+ }
+ /* restart */
+ set_roundbox_vertex_data(&vflag_step, last_data);
+ set_roundbox_vertex(&vflag_step, 0, 0, 0, true, false, OUTLINE);
+ /* Outlines */
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ for (int c = 0; c < 4; c++) {
+ for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
+ set_roundbox_vertex(&vflag_step, c, a, j, true, false, OUTLINE);
+ set_roundbox_vertex(&vflag_step, c, a, j, false, false, OUTLINE);
+ }
+ }
+ /* Close the loop. */
+ set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, OUTLINE);
+ last_data = set_roundbox_vertex(&vflag_step, 0, 0, j, false, false, OUTLINE);
+ }
+ /* restart */
+ set_roundbox_vertex_data(&vflag_step, last_data);
+ set_roundbox_vertex(&vflag_step, 0, 0, 0, false, false, EMBOSS);
+ /* Emboss */
+ bool rev = false; /* go back and forth : avoid degenerate triangle (but beware of backface cull) */
+ for (int j = 0; j < WIDGET_AA_JITTER; j++, rev = !rev) {
+ for (int c = (rev) ? 1 : 0; (rev) ? c >= 0 : c < 2; (rev) ? c-- : c++) {
+ int sta = (rev) ? WIDGET_CURVE_RESOLU - 1 : 0;
+ int end = WIDGET_CURVE_RESOLU;
+ for (int a = sta; (rev) ? a >= 0 : a < end; (rev) ? a-- : a++) {
+ set_roundbox_vertex(&vflag_step, c, a, j, false, false, EMBOSS);
+ last_data = set_roundbox_vertex(&vflag_step, c, a, j, false, true, EMBOSS);
+ }
+ }
+ }
+ if (tria) {
+ roundbox_batch_add_tria(&vflag_step, tria, last_data);
+ }
+ g_ui_batch_cache.roundbox_widget[tria] = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ gpu_batch_presets_register(g_ui_batch_cache.roundbox_widget[tria]);
+ }
+ return g_ui_batch_cache.roundbox_widget[tria];
+}
+
+Gwn_Batch *ui_batch_roundbox_get(bool filled, bool antialiased)
+{
+ Gwn_Batch **batch = NULL;
+
+ if (filled) {
+ if (antialiased)
+ batch = &g_ui_batch_cache.roundbox_simple_aa;
+ else
+ batch = &g_ui_batch_cache.roundbox_simple;
+ }
+ else {
+ if (antialiased)
+ BLI_assert(0); /* Use GL_LINE_SMOOTH instead!!: */
+ else
+ batch = &g_ui_batch_cache.roundbox_simple_outline;
+ }
+
+ if (*batch == NULL) {
+ uint32_t last_data;
+ Gwn_VertBufRaw vflag_step;
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format());
+ int vcount = WIDGET_SIZE_MAX;
+ vcount += (filled) ? 2 : 0;
+ vcount *= (antialiased) ? WIDGET_AA_JITTER : 1;
+ GWN_vertbuf_data_alloc(vbo, vcount);
+ GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+
+ if (filled) {
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ if (!antialiased) {
+ j = NO_AA;
+ }
+ /* restart */
+ set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, INNER);
+ for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
+ for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) {
+ last_data = set_roundbox_vertex(&vflag_step, c1, a1, j, true, false, INNER);
+ last_data = set_roundbox_vertex(&vflag_step, c2, a2, j, true, false, INNER);
+ }
+ }
+ /* restart */
+ set_roundbox_vertex_data(&vflag_step, last_data);
+ if (!antialiased) {
+ break;
+ }
+ }
+ *batch = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ else {
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ if (!antialiased) {
+ j = NO_AA;
+ }
+ for (int c = 0; c < 4; c++) {
+ for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
+ set_roundbox_vertex(&vflag_step, c, a, j, true, false, INNER);
+ }
+ }
+ if (!antialiased) {
+ break;
+ }
+ }
+ *batch = GWN_batch_create_ex(GWN_PRIM_LINE_LOOP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+
+ gpu_batch_presets_register(*batch);
+ }
+ return *batch;
+}
+
+Gwn_Batch *ui_batch_roundbox_shadow_get(void)
+{
+ if (g_ui_batch_cache.roundbox_shadow == NULL) {
+ uint32_t last_data;
+ Gwn_VertBufRaw vflag_step;
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format());
+ int vcount = (WIDGET_SIZE_MAX + 1) * 2 + 2 + WIDGET_SIZE_MAX;
+ GWN_vertbuf_data_alloc(vbo, vcount);
+ GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step);
+
+ for (int c = 0; c < 4; c++) {
+ for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) {
+ set_roundbox_vertex(&vflag_step, c, a, NO_AA, true, false, INNER);
+ set_roundbox_vertex(&vflag_step, c, a, NO_AA, false, false, INNER);
+ }
+ }
+ /* close loop */
+ last_data = set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, true, false, INNER);
+ last_data = set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, false, false, INNER);
+ /* restart */
+ set_roundbox_vertex_data(&vflag_step, last_data);
+ set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, true, false, INNER);
+ /* filled */
+ for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) {
+ for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) {
+ set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER);
+ set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER);
+ }
+ }
+ g_ui_batch_cache.roundbox_shadow = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ gpu_batch_presets_register(g_ui_batch_cache.roundbox_shadow);
+ }
+ return g_ui_batch_cache.roundbox_shadow;
+}
+
+#undef INNER
+#undef OUTLINE
+#undef EMBOSS
+#undef NO_AA
+
/* ************************************************* */
-void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3)
+void UI_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3,
+ const float color[4])
{
float tri_arr[3][2] = {{x1, y1}, {x2, y2}, {x3, y3}};
- float color[4];
- int j;
+ float draw_color[4];
+
+ copy_v4_v4(draw_color, color);
+ /* Note: This won't give back the original color. */
+ draw_color[3] *= 1.0f / WIDGET_AA_JITTER;
- glEnable(GL_BLEND);
- glGetFloatv(GL_CURRENT_COLOR, color);
- color[3] *= 0.125f;
- glColor4fv(color);
+ GPU_blend(true);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, tri_arr);
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4fv(draw_color);
+ immBegin(GWN_PRIM_TRIS, 3 * WIDGET_AA_JITTER);
/* for each AA step */
- for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslate2fv(jit[j]);
- glDrawArrays(GL_TRIANGLES, 0, 3);
- glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ immVertex2f(pos, tri_arr[0][0] + jit[j][0], tri_arr[0][1] + jit[j][1]);
+ immVertex2f(pos, tri_arr[1][0] + jit[j][0], tri_arr[1][1] + jit[j][1]);
+ immVertex2f(pos, tri_arr[2][0] + jit[j][0], tri_arr[2][1] + jit[j][1]);
}
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisable(GL_BLEND);
+ immEnd();
+
+ immUnbindProgram();
+
+ GPU_blend(false);
}
-void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha)
+/* triangle 'icon' inside rect */
+void ui_draw_anti_tria_rect(const rctf *rect, char dir, const float color[4])
{
- float color[4];
- int j;
-
- glEnable(GL_BLEND);
- glGetFloatv(GL_CURRENT_COLOR, color);
- if (use_alpha) {
- color[3] = 0.5f;
+ if (dir == 'h') {
+ float half = 0.5f * BLI_rctf_size_y(rect);
+ UI_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half, color);
}
- color[3] *= 0.125f;
- glColor4fv(color);
+ else {
+ float half = 0.5f * BLI_rctf_size_x(rect);
+ UI_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin, color);
+ }
+}
+
+
+void UI_draw_anti_fan(float tri_array[][2], unsigned int length, const float color[4])
+{
+ float draw_color[4];
+
+ copy_v4_v4(draw_color, color);
+ draw_color[3] *= 2.0f / WIDGET_AA_JITTER;
+
+ GPU_blend(true);
+
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4fv(draw_color);
- for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslate2fv(jit[j]);
- UI_draw_roundbox_gl_mode(mode, minx, miny, maxx, maxy, rad);
- glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
+ /* for each AA step */
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ immBegin(GWN_PRIM_TRI_FAN, length);
+ immVertex2f(pos, tri_array[0][0], tri_array[0][1]);
+ immVertex2f(pos, tri_array[1][0], tri_array[1][1]);
+
+ /* We jitter only the middle of the fan, the extremes are pinned. */
+ for (int i = 2; i < length - 1; i++) {
+ immVertex2f(pos, tri_array[i][0] + jit[j][0], tri_array[i][1] + jit[j][1]);
+ }
+
+ immVertex2f(pos, tri_array[length - 1][0], tri_array[length - 1][1]);
+ immEnd();
}
- glDisable(GL_BLEND);
+ immUnbindProgram();
+
+ GPU_blend(false);
}
static void widget_init(uiWidgetBase *wtb)
@@ -260,11 +585,16 @@ static void widget_init(uiWidgetBase *wtb)
wtb->totvert = wtb->halfwayvert = 0;
wtb->tria1.tot = 0;
wtb->tria2.tot = 0;
+ wtb->tria1.type = ROUNDBOX_TRIA_NONE;
+ wtb->tria1.size = 0;
+ wtb->tria2.size = 0;
wtb->draw_inner = true;
wtb->draw_outline = true;
wtb->draw_emboss = true;
- wtb->draw_shadedir = true;
+
+ wtb->uniform_params.shade_dir = 1.0f;
+ wtb->uniform_params.alpha_discard = 1.0f;
}
/* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
@@ -375,6 +705,17 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, const rcti *re
if (2.0f * (radi + 1.0f) > minsize)
radi = 0.5f * minsize - U.pixelsize;
+ wt->uniform_params.rad = rad;
+ wt->uniform_params.radi = radi;
+ wt->uniform_params.facxi = facxi;
+ wt->uniform_params.facyi = facyi;
+ wt->uniform_params.round_corners[0] = (roundboxalign & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f;
+ wt->uniform_params.round_corners[1] = (roundboxalign & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f;
+ wt->uniform_params.round_corners[2] = (roundboxalign & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f;
+ wt->uniform_params.round_corners[3] = (roundboxalign & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f;
+ BLI_rctf_rcti_copy(&wt->uniform_params.rect, rect);
+ BLI_rctf_init(&wt->uniform_params.recti, minxi, maxxi, minyi, maxyi);
+
/* mult */
for (a = 0; a < WIDGET_CURVE_RESOLU; a++) {
veci[a][0] = radi * cornervec[a][0];
@@ -519,23 +860,30 @@ static void shape_preset_init_trias_ex(
float centx, centy, sizex, sizey, minsize;
int a, i1 = 0, i2 = 1;
- minsize = min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect));
+ if (where == 'r' || where == 'l') {
+ minsize = BLI_rcti_size_y(rect);
+ }
+ else {
+ minsize = BLI_rcti_size_x(rect);
+ }
/* center position and size */
centx = (float)rect->xmin + 0.4f * minsize;
centy = (float)rect->ymin + 0.5f * minsize;
- sizex = sizey = -0.5f * triasize * minsize;
+ tria->size = sizex = sizey = -0.5f * triasize * minsize;
if (where == 'r') {
centx = (float)rect->xmax - 0.4f * minsize;
sizex = -sizex;
}
else if (where == 't') {
+ centx = (float)rect->xmin + 0.5f * minsize;
centy = (float)rect->ymax - 0.5f * minsize;
sizey = -sizey;
i2 = 0; i1 = 1;
}
else if (where == 'b') {
+ centx = (float)rect->xmin + 0.5f * minsize;
sizex = -sizex;
i2 = 0; i1 = 1;
}
@@ -545,12 +893,16 @@ static void shape_preset_init_trias_ex(
tria->vec[a][1] = sizey * verts[a][i2] + centy;
}
+ tria->center[0] = centx;
+ tria->center[1] = centy;
+
tria->tot = tris_tot;
tria->index = tris;
}
static void shape_preset_init_number_arrows(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
{
+ tria->type = ROUNDBOX_TRIA_ARROWS;
shape_preset_init_trias_ex(
tria, rect, triasize, where,
g_shape_preset_number_arrow_vert, ARRAY_SIZE(g_shape_preset_number_arrow_vert),
@@ -559,6 +911,12 @@ static void shape_preset_init_number_arrows(uiWidgetTrias *tria, const rcti *rec
static void shape_preset_init_hold_action(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
{
+ tria->type = ROUNDBOX_TRIA_HOLD_ACTION_ARROW;
+ /* With the current changes to use batches for widget drawing, the code
+ * below is doing almost nothing effectively. 'where' doesn't work either,
+ * shader is currently hardcoded to work for the button triangle pointing
+ * at the lower right. The same limitation applies to other trias as well.
+ * XXX Should be addressed. */
shape_preset_init_trias_ex(
tria, rect, triasize, where,
g_shape_preset_hold_action_vert, ARRAY_SIZE(g_shape_preset_hold_action_vert),
@@ -567,29 +925,37 @@ static void shape_preset_init_hold_action(uiWidgetTrias *tria, const rcti *rect,
static void shape_preset_init_scroll_circle(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
{
+ tria->type = ROUNDBOX_TRIA_SCROLL;
shape_preset_init_trias_ex(
tria, rect, triasize, where,
g_shape_preset_scroll_circle_vert, ARRAY_SIZE(g_shape_preset_scroll_circle_vert),
g_shape_preset_scroll_circle_face, ARRAY_SIZE(g_shape_preset_scroll_circle_face));
}
-static void shape_preset_draw_trias(uiWidgetTrias *tria)
+static void widget_draw_vertex_buffer(unsigned int pos, unsigned int col, int mode,
+ const float quads_pos[WIDGET_SIZE_MAX][2],
+ const unsigned char quads_col[WIDGET_SIZE_MAX][4],
+ unsigned int totvert)
{
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, tria->vec);
- glDrawElements(GL_TRIANGLES, tria->tot * 3, GL_UNSIGNED_INT, tria->index);
- glDisableClientState(GL_VERTEX_ARRAY);
+ immBegin(mode, totvert);
+ for (int i = 0; i < totvert; ++i) {
+ if (quads_col)
+ immAttrib4ubv(col, quads_col[i]);
+ immVertex2fv(pos, quads_pos[i]);
+ }
+ immEnd();
}
static void shape_preset_trias_from_rect_menu(uiWidgetTrias *tria, const rcti *rect)
{
float centx, centy, size;
int a;
+ tria->type = ROUNDBOX_TRIA_MENU;
/* center position and size */
- centx = rect->xmax - 0.32f * BLI_rcti_size_y(rect);
- centy = rect->ymin + 0.50f * BLI_rcti_size_y(rect);
- size = 0.4f * BLI_rcti_size_y(rect);
+ tria->center[0] = centx = rect->xmax - 0.32f * BLI_rcti_size_y(rect);
+ tria->center[1] = centy = rect->ymin + 0.50f * BLI_rcti_size_y(rect);
+ tria->size = size = 0.4f * BLI_rcti_size_y(rect);
for (a = 0; a < 6; a++) {
tria->vec[a][0] = size * g_shape_preset_menu_arrow_vert[a][0] + centx;
@@ -604,11 +970,12 @@ static void shape_preset_trias_from_rect_checkmark(uiWidgetTrias *tria, const rc
{
float centx, centy, size;
int a;
+ tria->type = ROUNDBOX_TRIA_CHECK;
/* center position and size */
- centx = rect->xmin + 0.5f * BLI_rcti_size_y(rect);
- centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
- size = 0.5f * BLI_rcti_size_y(rect);
+ tria->center[0] = centx = rect->xmin + 0.5f * BLI_rcti_size_y(rect);
+ tria->center[1] = centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
+ tria->size = size = 0.5f * BLI_rcti_size_y(rect);
for (a = 0; a < 6; a++) {
tria->vec[a][0] = size * g_shape_preset_checkmark_vert[a][0] + centx;
@@ -658,187 +1025,213 @@ static void widget_verts_to_triangle_strip(uiWidgetBase *wtb, const int totvert,
copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[0]);
}
-static void widget_verts_to_triangle_strip_open(uiWidgetBase *wtb, const int totvert, float triangle_strip[WIDGET_SIZE_MAX * 2][2])
-{
- int a;
- for (a = 0; a < totvert; a++) {
- triangle_strip[a * 2][0] = wtb->outer_v[a][0];
- triangle_strip[a * 2][1] = wtb->outer_v[a][1];
- triangle_strip[a * 2 + 1][0] = wtb->outer_v[a][0];
- triangle_strip[a * 2 + 1][1] = wtb->outer_v[a][1] - 1.0f;
- }
-}
-
-static void widgetbase_outline(uiWidgetBase *wtb)
+static void widgetbase_outline(uiWidgetBase *wtb, unsigned int pos)
{
float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2);
- glDisableClientState(GL_VERTEX_ARRAY);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2);
}
-static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
+static void widgetbase_set_uniform_alpha_discard(
+ uiWidgetBase *wtb,
+ const bool alpha_check,
+ const float discard_factor)
{
- int j, a;
+ if (alpha_check) {
+ wtb->uniform_params.alpha_discard = -discard_factor;
+ }
+ else {
+ wtb->uniform_params.alpha_discard = discard_factor;
+ }
+}
- glEnable(GL_BLEND);
+static void widgetbase_set_uniform_alpha_check(
+ uiWidgetBase *wtb,
+ const bool alpha_check)
+{
+ const float discard_factor = fabs(wtb->uniform_params.alpha_discard);
+ widgetbase_set_uniform_alpha_discard(wtb, alpha_check, discard_factor);
+}
- /* backdrop non AA */
- if (wtb->draw_inner) {
- BLI_assert(wtb->totvert != 0);
- if (wcol->shaded == 0) {
- if (wcol->alpha_check) {
- float inner_v_half[WIDGET_SIZE_MAX][2];
- float x_mid = 0.0f; /* used for dumb clamping of values */
+static void widgetbase_set_uniform_discard_factor(
+ uiWidgetBase *wtb,
+ const float discard_factor)
+{
+ bool alpha_check = wtb->uniform_params.alpha_discard < 0.0f;
+ widgetbase_set_uniform_alpha_discard(wtb, alpha_check, discard_factor);
+}
- /* dark checkers */
- glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
+static void widgetbase_set_uniform_colors_ubv(
+ uiWidgetBase *wtb,
+ const unsigned char *col1, const unsigned char *col2,
+ const unsigned char *outline,
+ const unsigned char *emboss,
+ const unsigned char *tria,
+ const bool alpha_check)
+{
+ widgetbase_set_uniform_alpha_check(wtb, alpha_check);
+ rgba_float_args_set_ch(wtb->uniform_params.color_inner1, col1[0], col1[1], col1[2], col1[3]);
+ rgba_float_args_set_ch(wtb->uniform_params.color_inner2, col2[0], col2[1], col2[2], col2[3]);
+ rgba_float_args_set_ch(wtb->uniform_params.color_outline, outline[0], outline[1], outline[2], outline[3]);
+ rgba_float_args_set_ch(wtb->uniform_params.color_emboss, emboss[0], emboss[1], emboss[2], emboss[3]);
+ rgba_float_args_set_ch(wtb->uniform_params.color_tria, tria[0], tria[1], tria[2], tria[3]);
+}
- /* light checkers */
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_CHECKER_8PX);
+/* keep in sync with shader */
+#define MAX_WIDGET_BASE_BATCH 6
+#define MAX_WIDGET_PARAMETERS 11
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
+struct {
+ Gwn_Batch *batch; /* Batch type */
+ uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH];
+ int count;
+ bool enabled;
+} g_widget_base_batch = {0};
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+void UI_widgetbase_draw_cache_flush(void)
+{
+ float checker_params[3] = {UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f};
- /* alpha fill */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ if (g_widget_base_batch.count == 0)
+ return;
- glColor4ubv((unsigned char *)wcol->inner);
+ Gwn_Batch *batch = g_widget_base_batch.batch;
+ if (g_widget_base_batch.count == 1) {
+ /* draw single */
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GWN_batch_uniform_4fv_array(batch, "parameters", MAX_WIDGET_PARAMETERS, (float *)g_widget_base_batch.params);
+ GWN_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
+ GWN_batch_draw(batch);
+ }
+ else {
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE_INST);
+ GWN_batch_uniform_4fv_array(batch, "parameters", MAX_WIDGET_PARAMETERS * MAX_WIDGET_BASE_BATCH,
+ (float *)g_widget_base_batch.params);
+ GWN_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
+ gpuBindMatrices(batch->interface);
+ GWN_batch_draw_range_ex(batch, 0, g_widget_base_batch.count, true);
+ GWN_batch_program_use_end(batch);
+ }
+ g_widget_base_batch.count = 0;
+}
- for (a = 0; a < wtb->totvert; a++) {
- x_mid += wtb->inner_v[a][0];
- }
- x_mid /= wtb->totvert;
+void UI_widgetbase_draw_cache_begin(void)
+{
+ BLI_assert(g_widget_base_batch.enabled == false);
+ g_widget_base_batch.enabled = true;
+}
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
+void UI_widgetbase_draw_cache_end(void)
+{
+ BLI_assert(g_widget_base_batch.enabled == true);
+ g_widget_base_batch.enabled = false;
- /* 1/2 solid color */
- glColor4ub(wcol->inner[0], wcol->inner[1], wcol->inner[2], 255);
+ GPU_blend(true);
- for (a = 0; a < wtb->totvert; a++) {
- inner_v_half[a][0] = MIN2(wtb->inner_v[a][0], x_mid);
- inner_v_half[a][1] = wtb->inner_v[a][1];
- }
+ UI_widgetbase_draw_cache_flush();
- glVertexPointer(2, GL_FLOAT, 0, inner_v_half);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
- glDisableClientState(GL_VERTEX_ARRAY);
- }
- else {
- /* simple fill */
- glColor4ubv((unsigned char *)wcol->inner);
+ GPU_blend(false);
+}
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
- glDisableClientState(GL_VERTEX_ARRAY);
- }
+static void draw_widgetbase_batch(Gwn_Batch *batch, uiWidgetBase *wtb)
+{
+ wtb->uniform_params.tria1_size = wtb->tria1.size;
+ wtb->uniform_params.tria2_size = wtb->tria2.size;
+ copy_v2_v2(wtb->uniform_params.tria1_center, wtb->tria1.center);
+ copy_v2_v2(wtb->uniform_params.tria2_center, wtb->tria2.center);
+
+ if (g_widget_base_batch.enabled) {
+ if (g_widget_base_batch.batch == NULL) {
+ g_widget_base_batch.batch = ui_batch_roundbox_widget_get(ROUNDBOX_TRIA_ARROWS);
}
- else {
- char col1[4], col2[4];
- unsigned char col_array[WIDGET_SIZE_MAX * 4];
- unsigned char *col_pt = col_array;
-
- shadecolors4(col1, col2, wcol->inner, wcol->shadetop, wcol->shadedown);
-
- for (a = 0; a < wtb->totvert; a++, col_pt += 4) {
- round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->draw_shadedir ? 1 : 0]);
- }
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glColorPointer(4, GL_UNSIGNED_BYTE, 0, col_array);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
+ /* draw multi */
+ if (batch != g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE] &&
+ batch != g_widget_base_batch.batch)
+ {
+ /* issue previous calls before changing batch type. */
+ UI_widgetbase_draw_cache_flush();
+ g_widget_base_batch.batch = batch;
}
- }
- /* for each AA step */
- if (wtb->draw_outline) {
- BLI_assert(wtb->totvert != 0);
- float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
- float triangle_strip_emboss[WIDGET_SIZE_MAX * 2][2]; /* only for emboss */
-
- const unsigned char tcol[4] = {
- wcol->outline[0],
- wcol->outline[1],
- wcol->outline[2],
- wcol->outline[3] / WIDGET_AA_JITTER,
- };
- unsigned char emboss[4];
+ /* No need to change batch if tria is not visible. Just scale it to 0. */
+ if (batch == g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE]) {
+ wtb->uniform_params.tria1_size = wtb->uniform_params.tria2_size = 0;
+ }
- widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
+ g_widget_base_batch.params[g_widget_base_batch.count] = wtb->uniform_params;
+ g_widget_base_batch.count++;
- if (wtb->draw_emboss) {
- widget_verts_to_triangle_strip_open(wtb, wtb->halfwayvert, triangle_strip_emboss);
- UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss);
+ if (g_widget_base_batch.count == MAX_WIDGET_BASE_BATCH) {
+ UI_widgetbase_draw_cache_flush();
}
+ }
+ else {
+ float checker_params[3] = {UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f};
+ /* draw single */
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
+ GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&wtb->uniform_params);
+ GWN_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
+ GWN_batch_draw(batch);
+ }
+}
- glEnableClientState(GL_VERTEX_ARRAY);
-
- for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslate2fv(jit[j]);
+static void widgetbase_draw(uiWidgetBase *wtb, const uiWidgetColors *wcol)
+{
+ unsigned char inner_col1[4] = {0};
+ unsigned char inner_col2[4] = {0};
+ unsigned char emboss_col[4] = {0};
+ unsigned char outline_col[4] = {0};
+ unsigned char tria_col[4] = {0};
+ /* For color widget. */
+ bool alpha_check = (wcol->alpha_check && (wcol->shaded == 0));
- /* outline */
- glColor4ubv(tcol);
+ GPU_blend(true);
- glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2);
+ /* backdrop non AA */
+ if (wtb->draw_inner) {
+ if (wcol->shaded == 0) {
+ /* simple fill */
+ inner_col1[0] = inner_col2[0] = (unsigned char)wcol->inner[0];
+ inner_col1[1] = inner_col2[1] = (unsigned char)wcol->inner[1];
+ inner_col1[2] = inner_col2[2] = (unsigned char)wcol->inner[2];
+ inner_col1[3] = inner_col2[3] = (unsigned char)wcol->inner[3];
+ }
+ else {
+ /* gradient fill */
+ shadecolors4((char *)inner_col1, (char *)inner_col2, wcol->inner, wcol->shadetop, wcol->shadedown);
+ }
+ }
- /* emboss bottom shadow */
- if (wtb->draw_emboss) {
- if (emboss[3]) {
- glColor4ubv(emboss);
- glVertexPointer(2, GL_FLOAT, 0, triangle_strip_emboss);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->halfwayvert * 2);
- }
- }
+ if (wtb->draw_outline) {
+ outline_col[0] = wcol->outline[0];
+ outline_col[1] = wcol->outline[1];
+ outline_col[2] = wcol->outline[2];
+ outline_col[3] = wcol->outline[3] / WIDGET_AA_JITTER;
- glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
+ /* emboss bottom shadow */
+ if (wtb->draw_emboss) {
+ UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss_col);
}
+ }
- glDisableClientState(GL_VERTEX_ARRAY);
+ if (wtb->tria1.type != ROUNDBOX_TRIA_NONE) {
+ tria_col[0] = wcol->item[0];
+ tria_col[1] = wcol->item[1];
+ tria_col[2] = wcol->item[2];
+ tria_col[3] = (unsigned char)((float)wcol->item[3] / WIDGET_AA_JITTER);
}
- /* decoration */
- if (wtb->tria1.tot || wtb->tria2.tot) {
- const unsigned char tcol[4] = {
- wcol->item[0],
- wcol->item[1],
- wcol->item[2],
- (unsigned char)((float)wcol->item[3] / WIDGET_AA_JITTER),
- };
- glColor4ubv(tcol);
-
- /* for each AA step */
- for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslate2fv(jit[j]);
-
- if (wtb->tria1.tot) {
- shape_preset_draw_trias(&wtb->tria1);
- }
- if (wtb->tria2.tot) {
- shape_preset_draw_trias(&wtb->tria2);
- }
+ /* Draw everything in one drawcall */
+ if (inner_col1[3] || inner_col2[3] || outline_col[3] || emboss_col[3] || tria_col[3] || alpha_check) {
+ widgetbase_set_uniform_colors_ubv(wtb, inner_col1, inner_col2, outline_col, emboss_col, tria_col, alpha_check);
- glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
- }
+ Gwn_Batch *roundbox_batch = ui_batch_roundbox_widget_get(wtb->tria1.type);
+ draw_widgetbase_batch(roundbox_batch, wtb);
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
/* *********************** text/icon ************************************** */
@@ -876,16 +1269,16 @@ static int ui_but_draw_menu_icon(const uiBut *but)
/* icons have been standardized... and this call draws in untransformed coordinates */
static void widget_draw_icon_ex(
- const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, const bool show_menu_icon,
- const int icon_size)
+ const uiBut *but, BIFIconID icon, float alpha,
+ const rcti *rect, const int icon_size)
{
float xs = 0.0f, ys = 0.0f;
float aspect, height;
if (but->flag & UI_BUT_ICON_PREVIEW) {
- glEnable(GL_BLEND);
+ GPU_blend(true);
widget_draw_preview(icon, alpha, rect);
- glDisable(GL_BLEND);
+ GPU_blend(false);
return;
}
@@ -913,14 +1306,14 @@ static void widget_draw_icon_ex(
}
}
- glEnable(GL_BLEND);
+ GPU_blend(true);
if (icon && icon != ICON_BLANK1) {
float ofs = 1.0f / aspect;
if (but->drawflag & UI_BUT_ICON_LEFT) {
/* special case - icon_only pie buttons */
- if (ui_block_is_pie_menu(but->block) && but->type != UI_BTYPE_MENU && but->str && but->str[0] == '\0')
+ if (ui_block_is_pie_menu(but->block) && !ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_POPOVER) && but->str && but->str[0] == '\0')
xs = rect->xmin + 2.0f * ofs;
else if (but->dt == UI_EMBOSS_NONE || but->type == UI_BTYPE_LABEL)
xs = rect->xmin + 2.0f * ofs;
@@ -943,24 +1336,44 @@ static void widget_draw_icon_ex(
float rgb[3] = {1.25f, 1.25f, 1.25f};
UI_icon_draw_aspect_color(xs, ys, icon, aspect, rgb);
}
- else
+ else if ((but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW)) || !UI_but_is_tool(but)) {
UI_icon_draw_aspect(xs, ys, icon, aspect, alpha);
+ }
+ else {
+ const bTheme *btheme = UI_GetTheme();
+ UI_icon_draw_desaturate(xs, ys, icon, aspect, alpha, 1.0 - btheme->tui.icon_saturation);
+ }
}
- if (show_menu_icon) {
- xs = rect->xmax - UI_DPI_ICON_SIZE - aspect;
- ys = (rect->ymin + rect->ymax - height) / 2.0f;
-
- UI_icon_draw_aspect(xs, ys, ICON_RIGHTARROW_THIN, aspect, alpha);
- }
-
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
static void widget_draw_icon(
- const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, const bool show_menu_icon)
+ const uiBut *but, BIFIconID icon, float alpha, const rcti *rect)
{
- widget_draw_icon_ex(but, icon, alpha, rect, show_menu_icon, ICON_DEFAULT_HEIGHT);
+ widget_draw_icon_ex(but, icon, alpha, rect, ICON_DEFAULT_HEIGHT);
+}
+
+static void widget_draw_submenu_tria(const uiBut *but, const rcti *rect, const uiWidgetColors *wcol)
+{
+ const float aspect = but->block->aspect / UI_DPI_FAC;
+ const int tria_height = (int)(ICON_DEFAULT_HEIGHT / aspect);
+ const int tria_width = (int)(ICON_DEFAULT_WIDTH / aspect) - 2 * U.pixelsize;
+ const int xs = rect->xmax - tria_width;
+ const int ys = (rect->ymin + rect->ymax - tria_height) / 2.0f;
+ float col[4];
+ rctf tria_rect;
+
+ rgba_uchar_to_float(col, (const uchar *)wcol->text);
+ col[3] *= 0.8f;
+
+ BLI_rctf_init(&tria_rect, xs, xs + tria_width, ys, ys + tria_height);
+ BLI_rctf_scale(&tria_rect, 0.4f);
+
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
+ ui_draw_anti_tria_rect(&tria_rect, 'h', col);
}
static void ui_text_clip_give_prev_off(uiBut *but, const char *str)
@@ -1120,6 +1533,8 @@ float UI_text_clip_middle_ex(
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
}
+ BLI_assert(strwidth <= okwidth);
+
return strwidth;
}
@@ -1129,7 +1544,7 @@ float UI_text_clip_middle_ex(
static void ui_text_clip_middle(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
{
/* No margin for labels! */
- const int border = ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_MENU) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
+ const int border = ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_MENU, UI_BTYPE_POPOVER) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
const float okwidth = (float)max_ii(BLI_rcti_size_x(rect) - border, 0);
const size_t max_len = sizeof(but->drawstr);
const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
@@ -1145,7 +1560,7 @@ static void ui_text_clip_middle(uiFontStyle *fstyle, uiBut *but, const rcti *rec
static void ui_text_clip_middle_protect_right(uiFontStyle *fstyle, uiBut *but, const rcti *rect, const char rsep)
{
/* No margin for labels! */
- const int border = ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_MENU) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
+ const int border = ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_MENU, UI_BTYPE_POPOVER) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
const float okwidth = (float)max_ii(BLI_rcti_size_x(rect) - border, 0);
const size_t max_len = sizeof(but->drawstr);
const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
@@ -1298,6 +1713,7 @@ static void widget_draw_text_ime_underline(
int ofs_x, width;
int rect_x = BLI_rcti_size_x(rect);
int sel_start = ime_data->sel_start, sel_end = ime_data->sel_end;
+ float fcol[4];
if (drawstr[0] != 0) {
if (but->pos >= but->ofs) {
@@ -1311,8 +1727,8 @@ static void widget_draw_text_ime_underline(
fstyle->uifont_id, drawstr + but->ofs,
ime_data->composite_len + but->pos - but->ofs);
- glColor4ubv((unsigned char *)wcol->text);
- UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 1);
+ rgba_uchar_to_float(fcol, wcol->text);
+ UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 1, fcol);
/* draw the thick line */
if (sel_start != -1 && sel_end != -1) {
@@ -1330,7 +1746,7 @@ static void widget_draw_text_ime_underline(
fstyle->uifont_id, drawstr + but->ofs,
sel_end + sel_start - but->ofs);
- UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 2);
+ UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 2, fcol);
}
}
}
@@ -1405,6 +1821,10 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
int selsta_draw, selwidth_draw;
if (drawstr[0] != 0) {
+ /* We are drawing on top of widget bases. Flush cache. */
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
if (but->selsta >= but->ofs) {
selsta_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selsta - but->ofs);
@@ -1415,11 +1835,16 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
selwidth_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selend - but->ofs);
- glColor4ubv((unsigned char *)wcol->item);
- glRecti(rect->xmin + selsta_draw,
- rect->ymin + 2,
- min_ii(rect->xmin + selwidth_draw, rect->xmax - 2),
- rect->ymax - 2);
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4ubv((unsigned char *)wcol->item);
+ immRecti(pos, rect->xmin + selsta_draw,
+ rect->ymin + 2,
+ min_ii(rect->xmin + selwidth_draw, rect->xmax - 2),
+ rect->ymax - 2);
+
+ immUnbindProgram();
}
}
@@ -1441,14 +1866,23 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
else {
t = 0;
}
+ /* We are drawing on top of widget bases. Flush cache. */
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
+
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glColor3f(0.2, 0.6, 0.9);
+ immUniformColor3f(0.2f, 0.6f, 0.9f);
tx = rect->xmin + t + 2;
ty = rect->ymin + 2;
/* draw cursor */
- glRecti(rect->xmin + t, ty, tx, rect->ymax - 2);
+ immRecti(pos, rect->xmin + t, ty, tx, rect->ymax - 2);
+
+ immUnbindProgram();
}
#ifdef WITH_INPUT_IME
@@ -1473,7 +1907,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
#endif
/* cut string in 2 parts - only for menu entries */
- if ((but->block->flag & UI_BLOCK_LOOP) &&
+ if ((but->drawflag & UI_BUT_HAS_SHORTCUT) &&
(but->editstr == NULL))
{
if (but->flag & UI_BUT_HAS_SEP_CHAR) {
@@ -1509,44 +1943,46 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
}
#endif
- glColor4ubv((unsigned char *)wcol->text);
-
if (!use_right_only) {
/* for underline drawing */
float font_xofs, font_yofs;
- UI_fontstyle_draw_ex(
- fstyle, rect, drawstr + but->ofs,
- drawstr_left_len - but->ofs, &font_xofs, &font_yofs);
+ int drawlen = (drawstr_left_len == INT_MAX) ? strlen(drawstr + but->ofs) : (drawstr_left_len - but->ofs);
- if (but->menu_key != '\0') {
- char fixedbuf[128];
- const char *str;
+ if (drawlen > 0) {
+ UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs, (unsigned char *)wcol->text,
+ drawlen, &font_xofs, &font_yofs);
- BLI_strncpy(fixedbuf, drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawstr_left_len));
+ if (but->menu_key != '\0') {
+ char fixedbuf[128];
+ const char *str;
- str = strchr(fixedbuf, but->menu_key - 32); /* upper case */
- if (str == NULL)
- str = strchr(fixedbuf, but->menu_key);
+ BLI_strncpy(fixedbuf, drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawlen));
- if (str) {
- int ul_index = -1;
- float ul_advance;
+ str = strchr(fixedbuf, but->menu_key - 32); /* upper case */
+ if (str == NULL)
+ str = strchr(fixedbuf, but->menu_key);
- ul_index = (int)(str - fixedbuf);
+ if (str) {
+ int ul_index = -1;
+ float ul_advance;
- if (fstyle->kerning == 1) {
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
+ ul_index = (int)(str - fixedbuf);
+
+ if (fstyle->kerning == 1) {
+ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
- fixedbuf[ul_index] = '\0';
- ul_advance = BLF_width(fstyle->uifont_id, fixedbuf, ul_index);
+ fixedbuf[ul_index] = '\0';
+ ul_advance = BLF_width(fstyle->uifont_id, fixedbuf, ul_index);
- BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f);
- BLF_draw(fstyle->uifont_id, "_", 2);
+ BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f);
+ BLF_color4ubv(fstyle->uifont_id, (unsigned char *)wcol->text);
+ BLF_draw(fstyle->uifont_id, "_", 2);
- if (fstyle->kerning == 1) {
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ if (fstyle->kerning == 1) {
+ BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
}
}
}
@@ -1554,9 +1990,15 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* part text right aligned */
if (drawstr_right) {
+ char col[4];
+ copy_v4_v4_char(col, wcol->text);
+ if (but->drawflag & UI_BUT_HAS_SHORTCUT) {
+ col[3] *= 0.5f;
+ }
+
fstyle->align = UI_STYLE_TEXT_RIGHT;
rect->xmax -= UI_TEXT_CLIP_MARGIN;
- UI_fontstyle_draw(fstyle, rect, drawstr_right);
+ UI_fontstyle_draw(fstyle, rect, drawstr_right, (const uchar *)col);
}
}
@@ -1571,10 +2013,10 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
ui_but_text_password_hide(password_str, but, false);
/* check for button text label */
- if (but->type == UI_BTYPE_MENU && (but->flag & UI_BUT_NODE_LINK)) {
+ if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_POPOVER) && (but->flag & UI_BUT_NODE_LINK)) {
rcti temp = *rect;
temp.xmin = rect->xmax - BLI_rcti_size_y(rect) - 1;
- widget_draw_icon(but, ICON_LAYER_USED, alpha, &temp, false);
+ widget_draw_icon(but, ICON_LAYER_USED, alpha, &temp);
rect->xmax = temp.xmin;
}
@@ -1596,9 +2038,9 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* draw icon in rect above the space reserved for the label */
rect->ymin += text_size;
- glEnable(GL_BLEND);
+ GPU_blend(true);
widget_draw_preview(icon, alpha, rect);
- glDisable(GL_BLEND);
+ GPU_blend(false);
/* offset rect to draw label in */
rect->ymin -= text_size;
@@ -1609,25 +2051,52 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
}
/* Icons on the left with optional text label on the right */
else if (but->flag & UI_HAS_ICON || show_menu_icon) {
+ const bool is_tool = UI_but_is_tool(but);
+
+ /* XXX add way to draw icons at a different size!
+ * Use small icons for popup. */
+#ifdef USE_UI_TOOLBAR_HACK
+ const float aspect_orig = but->block->aspect;
+ if (is_tool && (but->block->flag & UI_BLOCK_POPOVER)) {
+ but->block->aspect *= 2.0f;
+ }
+#endif
+
const BIFIconID icon = (but->flag & UI_HAS_ICON) ? but->icon + but->iconadd : ICON_NONE;
- const float icon_size = ICON_DEFAULT_WIDTH_SCALE;
+ int icon_size_init = is_tool ? ICON_DEFAULT_HEIGHT_TOOLBAR : ICON_DEFAULT_HEIGHT;
+ const float icon_size = icon_size_init / (but->block->aspect / UI_DPI_FAC);
+
+#ifdef USE_UI_TOOLBAR_HACK
+ if (is_tool) {
+ /* pass (even if its a menu toolbar) */
+ but->drawflag |= UI_BUT_TEXT_LEFT;
+ but->drawflag |= UI_BUT_ICON_LEFT;
+ }
+#endif
/* menu item - add some more padding so menus don't feel cramped. it must
* be part of the button so that this area is still clickable */
- if (ui_block_is_pie_menu(but->block)) {
+ if (is_tool) {
+ /* pass (even if its a menu toolbar) */
+ }
+ else if (ui_block_is_pie_menu(but->block)) {
if (but->dt == UI_EMBOSS_RADIAL)
rect->xmin += 0.3f * U.widget_unit;
}
else if (ui_block_is_menu(but->block))
rect->xmin += 0.3f * U.widget_unit;
- widget_draw_icon(but, icon, alpha, rect, show_menu_icon);
-
- rect->xmin += icon_size;
- /* without this menu keybindings will overlap the arrow icon [#38083] */
+ widget_draw_icon(but, icon, alpha, rect);
if (show_menu_icon) {
- rect->xmax -= icon_size / 2.0f;
+ BLI_assert(but->block->content_hints & BLOCK_CONTAINS_SUBMENU_BUT);
+ widget_draw_submenu_tria(but, rect, wcol);
}
+
+#ifdef USE_UI_TOOLBAR_HACK
+ but->block->aspect = aspect_orig;
+#endif
+
+ rect->xmin += icon_size;
}
if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) {
@@ -1637,6 +2106,12 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
rect->xmax -= (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
}
+ /* Menu contains sub-menu items with triangle icon on their right. Shortcut
+ * strings should be drawn with some padding to the right then. */
+ if (ui_block_is_menu(but->block) && (but->block->content_hints & BLOCK_CONTAINS_SUBMENU_BUT)) {
+ rect->xmax -= UI_MENU_SUBMENU_PADDING;
+ }
+
/* extra icons, e.g. 'x' icon to clear text or icon for eyedropper */
if (extra_icon_type != UI_BUT_ICONEXTRA_NONE) {
rcti temp = *rect;
@@ -1644,10 +2119,10 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
- widget_draw_icon(but, ICON_PANEL_CLOSE, alpha, &temp, false);
+ widget_draw_icon(but, ICON_PANEL_CLOSE, alpha, &temp);
}
else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
- widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, false);
+ widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp);
}
else {
BLI_assert(0);
@@ -1680,6 +2155,9 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
widget_draw_text(fstyle, wcol, but, rect);
ui_but_text_password_hide(password_str, but, true);
+
+ /* if a widget uses font shadow it has to be deactivated now */
+ BLF_disable(fstyle->uifont_id, BLF_SHADOW);
}
#undef UI_TEXT_CLIP_MARGIN
@@ -1687,297 +2165,6 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* *********************** widget types ************************************* */
-static struct uiWidgetStateColors wcol_state_colors = {
- {115, 190, 76, 255},
- {90, 166, 51, 255},
- {240, 235, 100, 255},
- {215, 211, 75, 255},
- {180, 0, 255, 255},
- {153, 0, 230, 255},
- 0.5f, 0.0f
-};
-
-static struct uiWidgetColors wcol_num = {
- {25, 25, 25, 255},
- {180, 180, 180, 255},
- {153, 153, 153, 255},
- {90, 90, 90, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 1,
- -20, 0
-};
-
-static struct uiWidgetColors wcol_numslider = {
- {25, 25, 25, 255},
- {180, 180, 180, 255},
- {153, 153, 153, 255},
- {128, 128, 128, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 1,
- -20, 0
-};
-
-static struct uiWidgetColors wcol_text = {
- {25, 25, 25, 255},
- {153, 153, 153, 255},
- {153, 153, 153, 255},
- {90, 90, 90, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 1,
- 0, 25
-};
-
-static struct uiWidgetColors wcol_option = {
- {0, 0, 0, 255},
- {70, 70, 70, 255},
- {70, 70, 70, 255},
- {255, 255, 255, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 1,
- 15, -15
-};
-
-/* button that shows popup */
-static struct uiWidgetColors wcol_menu = {
- {0, 0, 0, 255},
- {70, 70, 70, 255},
- {70, 70, 70, 255},
- {255, 255, 255, 255},
-
- {255, 255, 255, 255},
- {204, 204, 204, 255},
-
- 1,
- 15, -15
-};
-
-/* button that starts pulldown */
-static struct uiWidgetColors wcol_pulldown = {
- {0, 0, 0, 255},
- {63, 63, 63, 255},
- {86, 128, 194, 255},
- {255, 255, 255, 255},
-
- {0, 0, 0, 255},
- {0, 0, 0, 255},
-
- 0,
- 25, -20
-};
-
-/* button inside menu */
-static struct uiWidgetColors wcol_menu_item = {
- {0, 0, 0, 255},
- {0, 0, 0, 0},
- {86, 128, 194, 255},
- {172, 172, 172, 128},
-
- {255, 255, 255, 255},
- {0, 0, 0, 255},
-
- 1,
- 38, 0
-};
-
-/* backdrop menu + title text color */
-static struct uiWidgetColors wcol_menu_back = {
- {0, 0, 0, 255},
- {25, 25, 25, 230},
- {45, 45, 45, 230},
- {100, 100, 100, 255},
-
- {160, 160, 160, 255},
- {255, 255, 255, 255},
-
- 0,
- 25, -20
-};
-
-/* pie menus */
-static struct uiWidgetColors wcol_pie_menu = {
- {10, 10, 10, 200},
- {25, 25, 25, 230},
- {140, 140, 140, 255},
- {45, 45, 45, 230},
-
- {160, 160, 160, 255},
- {255, 255, 255, 255},
-
- 1,
- 10, -10
-};
-
-
-/* tooltip color */
-static struct uiWidgetColors wcol_tooltip = {
- {0, 0, 0, 255},
- {25, 25, 25, 230},
- {45, 45, 45, 230},
- {100, 100, 100, 255},
-
- {255, 255, 255, 255},
- {255, 255, 255, 255},
-
- 0,
- 25, -20
-};
-
-static struct uiWidgetColors wcol_radio = {
- {0, 0, 0, 255},
- {70, 70, 70, 255},
- {86, 128, 194, 255},
- {255, 255, 255, 255},
-
- {255, 255, 255, 255},
- {0, 0, 0, 255},
-
- 1,
- 15, -15
-};
-
-static struct uiWidgetColors wcol_regular = {
- {25, 25, 25, 255},
- {153, 153, 153, 255},
- {100, 100, 100, 255},
- {25, 25, 25, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 0, 0
-};
-
-static struct uiWidgetColors wcol_tool = {
- {25, 25, 25, 255},
- {153, 153, 153, 255},
- {100, 100, 100, 255},
- {25, 25, 25, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 1,
- 15, -15
-};
-
-static struct uiWidgetColors wcol_box = {
- {25, 25, 25, 255},
- {128, 128, 128, 255},
- {100, 100, 100, 255},
- {25, 25, 25, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 0, 0
-};
-
-static struct uiWidgetColors wcol_toggle = {
- {25, 25, 25, 255},
- {153, 153, 153, 255},
- {100, 100, 100, 255},
- {25, 25, 25, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 0, 0
-};
-
-static struct uiWidgetColors wcol_scroll = {
- {50, 50, 50, 180},
- {80, 80, 80, 180},
- {100, 100, 100, 180},
- {128, 128, 128, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 1,
- 5, -5
-};
-
-static struct uiWidgetColors wcol_progress = {
- {0, 0, 0, 255},
- {190, 190, 190, 255},
- {100, 100, 100, 180},
- {128, 128, 128, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 0, 0
-};
-
-static struct uiWidgetColors wcol_list_item = {
- {0, 0, 0, 255},
- {0, 0, 0, 0},
- {86, 128, 194, 255},
- {90, 90, 90, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 0, 0
-};
-
-/* free wcol struct to play with */
-static struct uiWidgetColors wcol_tmp = {
- {0, 0, 0, 255},
- {128, 128, 128, 255},
- {100, 100, 100, 255},
- {25, 25, 25, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 0, 0
-};
-
-
-/* called for theme init (new theme) and versions */
-void ui_widget_color_init(ThemeUI *tui)
-{
- tui->wcol_regular = wcol_regular;
- tui->wcol_tool = wcol_tool;
- tui->wcol_text = wcol_text;
- tui->wcol_radio = wcol_radio;
- tui->wcol_option = wcol_option;
- tui->wcol_toggle = wcol_toggle;
- tui->wcol_num = wcol_num;
- tui->wcol_numslider = wcol_numslider;
- tui->wcol_menu = wcol_menu;
- tui->wcol_pulldown = wcol_pulldown;
- tui->wcol_menu_back = wcol_menu_back;
- tui->wcol_pie_menu = wcol_pie_menu;
- tui->wcol_tooltip = wcol_tooltip;
- tui->wcol_menu_item = wcol_menu_item;
- tui->wcol_box = wcol_box;
- tui->wcol_scroll = wcol_scroll;
- tui->wcol_list_item = wcol_list_item;
- tui->wcol_progress = wcol_progress;
-
- tui->wcol_state = wcol_state_colors;
-}
-
/* ************ button callbacks, state ***************** */
static void widget_state_blend(char cp[3], const char cpstate[3], const float fac)
@@ -2006,6 +2193,13 @@ static void ui_widget_color_disabled(uiWidgetType *wt)
wt->wcol_theme = &wcol_theme_s;
}
+static void widget_active_color(char cp[3])
+{
+ cp[0] = cp[0] >= 240 ? 255 : cp[0] + 15;
+ cp[1] = cp[1] >= 240 ? 255 : cp[1] + 15;
+ cp[2] = cp[2] >= 240 ? 255 : cp[2] + 15;
+}
+
/* copy colors from theme, and set changes in it based on state */
static void widget_state(uiWidgetType *wt, int state)
{
@@ -2032,6 +2226,8 @@ static void widget_state(uiWidgetType *wt, int state)
widget_state_blend(wt->wcol.inner, wcol_state->inner_anim_sel, wcol_state->blend);
else if (state & UI_BUT_DRIVEN)
widget_state_blend(wt->wcol.inner, wcol_state->inner_driven_sel, wcol_state->blend);
+ else if (state & UI_BUT_OVERRIDEN)
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_overridden_sel, wcol_state->blend);
copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
@@ -2045,11 +2241,11 @@ static void widget_state(uiWidgetType *wt, int state)
widget_state_blend(wt->wcol.inner, wcol_state->inner_anim, wcol_state->blend);
else if (state & UI_BUT_DRIVEN)
widget_state_blend(wt->wcol.inner, wcol_state->inner_driven, wcol_state->blend);
+ else if (state & UI_BUT_OVERRIDEN)
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_overridden, wcol_state->blend);
if (state & UI_ACTIVE) { /* mouse over? */
- wt->wcol.inner[0] = wt->wcol.inner[0] >= 240 ? 255 : wt->wcol.inner[0] + 15;
- wt->wcol.inner[1] = wt->wcol.inner[1] >= 240 ? 255 : wt->wcol.inner[1] + 15;
- wt->wcol.inner[2] = wt->wcol.inner[2] >= 240 ? 255 : wt->wcol.inner[2] + 15;
+ widget_active_color(wt->wcol.inner);
}
}
@@ -2090,6 +2286,8 @@ static void widget_state_numslider(uiWidgetType *wt, int state)
widget_state_blend(wt->wcol.item, wcol_state->inner_anim_sel, blend);
else if (state & UI_BUT_DRIVEN)
widget_state_blend(wt->wcol.item, wcol_state->inner_driven_sel, blend);
+ else if (state & UI_BUT_OVERRIDEN)
+ widget_state_blend(wt->wcol.item, wcol_state->inner_overridden_sel, blend);
if (state & UI_SELECT)
SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
@@ -2101,6 +2299,8 @@ static void widget_state_numslider(uiWidgetType *wt, int state)
widget_state_blend(wt->wcol.item, wcol_state->inner_anim, blend);
else if (state & UI_BUT_DRIVEN)
widget_state_blend(wt->wcol.item, wcol_state->inner_driven, blend);
+ else if (state & UI_BUT_OVERRIDEN)
+ widget_state_blend(wt->wcol.item, wcol_state->inner_overridden, blend);
}
}
@@ -2126,15 +2326,9 @@ static void widget_state_nothing(uiWidgetType *wt, int UNUSED(state))
}
/* special case, button that calls pulldown */
-static void widget_state_pulldown(uiWidgetType *wt, int state)
+static void widget_state_pulldown(uiWidgetType *wt, int UNUSED(state))
{
wt->wcol = *(wt->wcol_theme);
-
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
- copy_v3_v3_char(wt->wcol.outline, wt->wcol.inner);
-
- if (state & UI_ACTIVE)
- copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
}
/* special case, pie menu items */
@@ -2150,18 +2344,22 @@ static void widget_state_pie_menu_item(uiWidgetType *wt, int state)
copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
wt->wcol.inner[3] = 64;
}
- /* regular disabled */
- else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
- widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
- }
- /* regular active */
- else if (state & UI_SELECT) {
- copy_v4_v4_char(wt->wcol.outline, wt->wcol.inner_sel);
- copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
- }
- else if (state & UI_ACTIVE) {
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
- copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+ else {
+ /* regular active */
+ if (state & (UI_SELECT | UI_ACTIVE)) {
+ copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+ }
+ else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ /* regular disabled */
+ widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
+ }
+
+ if (state & UI_SELECT) {
+ copy_v4_v4_char(wt->wcol.outline, wt->wcol.inner_sel);
+ }
+ else if (state & UI_ACTIVE) {
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
+ }
}
}
@@ -2178,14 +2376,19 @@ static void widget_state_menu_item(uiWidgetType *wt, int state)
copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
wt->wcol.inner[3] = 64;
}
- /* regular disabled */
- else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
- widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
- }
- /* regular active */
- else if (state & UI_ACTIVE) {
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
- copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+ else {
+ /* regular active */
+ if (state & UI_ACTIVE) {
+ copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+ }
+ else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ /* regular disabled */
+ widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
+ }
+
+ if (state & UI_ACTIVE) {
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
+ }
}
}
@@ -2219,22 +2422,23 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r
/* we draw a number of increasing size alpha quad strips */
alphastep = 3.0f * btheme->tui.menu_shadow_fac / radout;
- glEnableClientState(GL_VERTEX_ARRAY);
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
for (step = 1; step <= (int)radout; step++) {
float expfac = sqrtf(step / radout);
round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, (float)step);
- glColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
+ immUniformColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
widget_verts_to_triangle_strip(&wtb, totvert, triangle_strip);
- glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, totvert * 2); /* add + 2 for getting a complete soft rect. Now it skips top edge to allow transparent menus */
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, totvert * 2);
}
- glDisableClientState(GL_VERTEX_ARRAY);
+ immUnbindProgram();
}
static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction)
@@ -2258,33 +2462,33 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir
rect->ymax += 0.1f * U.widget_unit;
}
- glEnable(GL_BLEND);
- widget_softshadow(rect, roundboxalign, 0.25f * U.widget_unit);
+ GPU_blend(true);
+ widget_softshadow(rect, roundboxalign, wcol->roundness * U.widget_unit);
- round_box_edges(&wtb, roundboxalign, rect, 0.25f * U.widget_unit);
+ round_box_edges(&wtb, roundboxalign, rect, wcol->roundness * U.widget_unit);
wtb.draw_emboss = false;
widgetbase_draw(&wtb, wcol);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
-
static void ui_hsv_cursor(float x, float y)
{
- glPushMatrix();
- glTranslatef(x, y, 0.0f);
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glColor3f(1.0f, 1.0f, 1.0f);
- glutil_draw_filled_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 8);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+ imm_draw_circle_fill_2d(pos, x, y, 3.0f * U.pixelsize, 8);
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
- glColor3f(0.0f, 0.0f, 0.0f);
- glutil_draw_lined_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 12);
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
+ GPU_blend(true);
+ GPU_line_smooth(true);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ imm_draw_circle_wire_2d(pos, x, y, 3.0f * U.pixelsize, 12);
+ GPU_blend(false);
+ GPU_line_smooth(false);
- glPopMatrix();
+ immUnbindProgram();
}
void ui_hsvcircle_vals_from_pos(
@@ -2325,18 +2529,17 @@ void ui_hsvcircle_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float
static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
{
+ /* TODO(merwin): reimplement as shader for pixel-perfect colors */
+
const int tot = 64;
const float radstep = 2.0f * (float)M_PI / (float)tot;
const float centx = BLI_rcti_cent_x_fl(rect);
const float centy = BLI_rcti_cent_y_fl(rect);
float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
- /* gouraud triangle fan */
ColorPicker *cpicker = but->custom_data;
const float *hsv_ptr = cpicker->color_data;
- float xpos, ypos, ang = 0.0f;
float rgb[3], hsvo[3], hsv[3], col[3], colcent[3];
- int a;
bool color_profile = ui_but_is_colorpicker_display_space(but);
/* color */
@@ -2367,11 +2570,18 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
ui_color_picker_to_rgb(0.0f, 0.0f, hsv[2], colcent, colcent + 1, colcent + 2);
- glBegin(GL_TRIANGLE_FAN);
- glColor3fv(colcent);
- glVertex2f(centx, centy);
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
- for (a = 0; a <= tot; a++, ang += radstep) {
+ immBegin(GWN_PRIM_TRI_FAN, tot + 2);
+ immAttrib3fv(color, colcent);
+ immVertex2f(pos, centx, centy);
+
+ float ang = 0.0f;
+ for (int a = 0; a <= tot; a++, ang += radstep) {
float si = sinf(ang);
float co = cosf(ang);
@@ -2379,25 +2589,32 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
ui_color_picker_to_rgb_v(hsv, col);
- glColor3fv(col);
- glVertex2f(centx + co * radius, centy + si * radius);
+ immAttrib3fv(color, col);
+ immVertex2f(pos, centx + co * radius, centy + si * radius);
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
/* fully rounded outline */
- glPushMatrix();
- glTranslatef(centx, centy, 0.0f);
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
- glColor3ubv((unsigned char *)wcol->outline);
- glutil_draw_lined_arc(0.0f, M_PI * 2.0, radius, tot + 1);
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
- glPopMatrix();
+ format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ GPU_blend(true);
+ GPU_line_smooth(true);
+
+ immUniformColor3ubv((unsigned char *)wcol->outline);
+ imm_draw_circle_wire_2d(pos, centx, centy, radius, tot);
+
+ immUnbindProgram();
+
+ GPU_blend(false);
+ GPU_line_smooth(false);
/* cursor */
+ float xpos, ypos;
ui_hsvcircle_pos_from_vals(but, rect, hsvo, &xpos, &ypos);
-
ui_hsv_cursor(xpos, ypos);
}
@@ -2407,7 +2624,8 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha)
{
/* allows for 4 steps (red->yellow) */
- const float color_step = 1.0f / 48.0f;
+ const int steps = 48;
+ const float color_step = 1.0f / steps;
int a;
float h = hsv[0], s = hsv[1], v = hsv[2];
float dx, dy, sx1, sx2, sy;
@@ -2463,7 +2681,12 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
}
/* old below */
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ immBegin(GWN_PRIM_TRIS, steps * 3 * 6);
for (dx = 0.0f; dx < 0.999f; dx += color_step) { /* 0.999 = prevent float inaccuracy for steps */
const float dx_next = dx + color_step;
@@ -2521,22 +2744,29 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
sy = rect->ymin;
dy = (float)BLI_rcti_size_y(rect) / 3.0f;
- glBegin(GL_QUADS);
for (a = 0; a < 3; a++, sy += dy) {
- glColor4f(col0[a][0], col0[a][1], col0[a][2], alpha);
- glVertex2f(sx1, sy);
+ immAttrib4f(col, col0[a][0], col0[a][1], col0[a][2], alpha);
+ immVertex2f(pos, sx1, sy);
+
+ immAttrib4f(col, col1[a][0], col1[a][1], col1[a][2], alpha);
+ immVertex2f(pos, sx2, sy);
+
+ immAttrib4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
+ immVertex2f(pos, sx2, sy + dy);
- glColor4f(col1[a][0], col1[a][1], col1[a][2], alpha);
- glVertex2f(sx2, sy);
+ immAttrib4f(col, col0[a][0], col0[a][1], col0[a][2], alpha);
+ immVertex2f(pos, sx1, sy);
- glColor4f(col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
- glVertex2f(sx2, sy + dy);
+ immAttrib4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
+ immVertex2f(pos, sx2, sy + dy);
- glColor4f(col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha);
- glVertex2f(sx1, sy + dy);
+ immAttrib4f(col, col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha);
+ immVertex2f(pos, sx1, sy + dy);
}
- glEnd();
}
+ immEnd();
+
+ immUnbindProgram();
}
bool ui_but_is_colorpicker_display_space(uiBut *but)
@@ -2612,15 +2842,20 @@ static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect)
ui_hsv_cursor(x, y);
/* outline */
- glColor3ub(0, 0, 0);
- fdrawbox((rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ub(0, 0, 0);
+ imm_draw_box_wire_2d(pos, (rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
+ immUnbindProgram();
}
/* vertical 'value' slider, using new widget code */
static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
{
+ bTheme *btheme = UI_GetTheme();
+ uiWidgetColors *wcol = &btheme->tui.wcol_numslider;
uiWidgetBase wtb;
- const float rad = 0.5f * BLI_rcti_size_x(rect);
+ const float rad = wcol->roundness * BLI_rcti_size_x(rect);
float x, y;
float rgb[3], hsv[3], v;
bool color_profile = but->block->color_profile;
@@ -2654,13 +2889,21 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
/* setup temp colors */
- wcol_tmp.outline[0] = wcol_tmp.outline[1] = wcol_tmp.outline[2] = 0;
- wcol_tmp.inner[0] = wcol_tmp.inner[1] = wcol_tmp.inner[2] = 128;
- wcol_tmp.shadetop = 127;
- wcol_tmp.shadedown = -128;
- wcol_tmp.shaded = 1;
-
- widgetbase_draw(&wtb, &wcol_tmp);
+ widgetbase_draw(
+ &wtb,
+ &((uiWidgetColors){
+ .outline = {0, 0, 0, 255},
+ .inner = {128, 128, 128, 255},
+ .shadetop = 127,
+ .shadedown = -128,
+ .shaded = 1,
+ })
+ );
+
+ /* We are drawing on top of widget bases. Flush cache. */
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
/* cursor */
x = rect->xmin + 0.5f * BLI_rcti_size_x(rect);
@@ -2670,6 +2913,20 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
ui_hsv_cursor(x, y);
}
+/* Generic round-box drawing. */
+static void ui_draw_roundbox(const rcti *rect, const float rad, const uiWidgetColors *wcol)
+{
+ uiWidgetBase wtb;
+ widget_init(&wtb);
+ round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
+ widgetbase_draw(&wtb, wcol);
+
+ /* We are drawing on top of widget bases. Flush cache. */
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
+}
+
/* ************ separator, for menus etc ***************** */
static void ui_draw_separator(const rcti *rect, uiWidgetColors *wcol)
@@ -2682,19 +2939,29 @@ static void ui_draw_separator(const rcti *rect, uiWidgetColors *wcol)
30
};
- glEnable(GL_BLEND);
- glColor4ubv(col);
- glLineWidth(1.0f);
- sdrawline(rect->xmin, y, rect->xmax, y);
- glDisable(GL_BLEND);
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ GPU_blend(true);
+ immUniformColor4ubv(col);
+ GPU_line_width(1.0f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, rect->xmin, y);
+ immVertex2f(pos, rect->xmax, y);
+ immEnd();
+
+ GPU_blend(false);
+
+ immUnbindProgram();
}
/* ************ button callbacks, draw ***************** */
static void widget_numbut_draw(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, bool emboss)
{
uiWidgetBase wtb;
- const float rad = 0.5f * BLI_rcti_size_y(rect);
- float textofs = rad * 0.85f;
+ const float rad = wcol->roundness * BLI_rcti_size_y(rect);
+ const int handle_width = min_ii(BLI_rcti_size_x(rect) / 3, BLI_rcti_size_y(rect) * 0.7f);
if (state & UI_SELECT)
SWAP(short, wcol->shadetop, wcol->shadedown);
@@ -2710,14 +2977,80 @@ static void widget_numbut_draw(uiWidgetColors *wcol, rcti *rect, int state, int
}
/* decoration */
- if (!(state & UI_STATE_TEXT_INPUT)) {
- shape_preset_init_number_arrows(&wtb.tria1, rect, 0.6f, 'l');
- shape_preset_init_number_arrows(&wtb.tria2, rect, 0.6f, 'r');
- }
+ if ((state & UI_ACTIVE) && !(state & UI_STATE_TEXT_INPUT)) {
+ uiWidgetColors wcol_zone;
+ uiWidgetBase wtb_zone;
+ rcti rect_zone;
+ int roundboxalign_zone;
+
+ /* left arrow zone */
+ widget_init(&wtb_zone);
+ wtb_zone.draw_outline = false;
+ wtb_zone.draw_emboss = false;
+
+ wcol_zone = *wcol;
+ copy_v3_v3_char(wcol_zone.item, wcol->text);
+ if (state & UI_STATE_ACTIVE_LEFT) {
+ widget_active_color(wcol_zone.inner);
+ }
- widgetbase_draw(&wtb, wcol);
+ rect_zone = *rect;
+ rect_zone.xmax = rect->xmin + handle_width + U.pixelsize;
+ roundboxalign_zone = roundboxalign & ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
+ round_box_edges(&wtb_zone, roundboxalign_zone, &rect_zone, rad);
+
+ shape_preset_init_number_arrows(&wtb_zone.tria1, &rect_zone, 0.6f, 'l');
+ widgetbase_draw(&wtb_zone, &wcol_zone);
+
+ /* right arrow zone */
+ widget_init(&wtb_zone);
+ wtb_zone.draw_outline = false;
+ wtb_zone.draw_emboss = false;
+ wtb_zone.tria1.type = ROUNDBOX_TRIA_ARROWS;
+
+ wcol_zone = *wcol;
+ copy_v3_v3_char(wcol_zone.item, wcol->text);
+ if (state & UI_STATE_ACTIVE_RIGHT) {
+ widget_active_color(wcol_zone.inner);
+ }
+
+ rect_zone = *rect;
+ rect_zone.xmin = rect->xmax - handle_width - U.pixelsize;
+ roundboxalign_zone = roundboxalign & ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
+ round_box_edges(&wtb_zone, roundboxalign_zone, &rect_zone, rad);
+
+ shape_preset_init_number_arrows(&wtb_zone.tria2, &rect_zone, 0.6f, 'r');
+ widgetbase_draw(&wtb_zone, &wcol_zone);
+
+ /* middle highlight zone */
+ widget_init(&wtb_zone);
+ wtb_zone.draw_outline = false;
+ wtb_zone.draw_emboss = false;
+
+ wcol_zone = *wcol;
+ copy_v3_v3_char(wcol_zone.item, wcol->text);
+ if (!(state & (UI_STATE_ACTIVE_LEFT | UI_STATE_ACTIVE_RIGHT))) {
+ widget_active_color(wcol_zone.inner);
+ }
+
+ rect_zone = *rect;
+ rect_zone.xmin = rect->xmin + handle_width - U.pixelsize;
+ rect_zone.xmax = rect->xmax - handle_width + U.pixelsize;
+ round_box_edges(&wtb_zone, 0, &rect_zone, 0);
+ widgetbase_draw(&wtb_zone, &wcol_zone);
+
+ /* outline */
+ wtb.draw_inner = false;
+ widgetbase_draw(&wtb, wcol);
+ }
+ else {
+ /* inner and outline */
+ widgetbase_draw(&wtb, wcol);
+ }
if (!(state & UI_STATE_TEXT_INPUT)) {
+ const float textofs = 0.425f * BLI_rcti_size_y(rect);
+
/* text space */
rect->xmin += textofs;
rect->xmax -= textofs;
@@ -2737,53 +3070,6 @@ static void widget_numbut_embossn(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti
widget_numbut_draw(wcol, rect, state, roundboxalign, true);
}
-bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol)
-{
- float dist, vec[4][2];
-
- vec[0][0] = rect->xmin;
- vec[0][1] = rect->ymin;
- vec[3][0] = rect->xmax;
- vec[3][1] = rect->ymax;
-
- dist = 0.5f * fabsf(vec[0][0] - vec[3][0]);
-
- vec[1][0] = vec[0][0] + dist;
- vec[1][1] = vec[0][1];
-
- vec[2][0] = vec[3][0] - dist;
- vec[2][1] = vec[3][1];
-
- BKE_curve_forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], &coord_array[0][0], resol, sizeof(float[2]));
- BKE_curve_forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], &coord_array[0][1], resol, sizeof(float[2]));
-
- /* TODO: why return anything if always true? */
- return true;
-}
-
-#define LINK_RESOL 24
-void ui_draw_link_bezier(const rcti *rect)
-{
- float coord_array[LINK_RESOL + 1][2];
-
- if (ui_link_bezier_points(rect, coord_array, LINK_RESOL)) {
-#if 0 /* unused */
- /* we can reuse the dist variable here to increment the GL curve eval amount*/
- const float dist = 1.0f / (float)LINK_RESOL;
-#endif
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, coord_array);
- glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL + 1);
- glDisableClientState(GL_VERTEX_ARRAY);
-
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
- }
-}
-
/* function in use for buttons and for view2d sliders */
void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *slider, int state)
{
@@ -2798,11 +3084,11 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s
horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect));
if (horizontal)
- rad = 0.5f * BLI_rcti_size_y(rect);
+ rad = wcol->roundness * BLI_rcti_size_y(rect);
else
- rad = 0.5f * BLI_rcti_size_x(rect);
+ rad = wcol->roundness * BLI_rcti_size_x(rect);
- wtb.draw_shadedir = (horizontal) ? true : false;
+ wtb.uniform_params.shade_dir = (horizontal) ? 1.0f : 0.0;
/* draw back part, colors swapped and shading inverted */
if (horizontal)
@@ -2934,7 +3220,7 @@ static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int
/* round corners */
float value = but->a1;
- float offs = 0.25f * BLI_rcti_size_y(&rect_prog);
+ float offs = wcol->roundness * BLI_rcti_size_y(&rect_prog);
float w = value * BLI_rcti_size_x(&rect_prog);
/* ensure minimium size */
@@ -2957,96 +3243,85 @@ static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int
rect->xmax += (BLI_rcti_size_x(&rect_prog) / 2);
}
-static void widget_link(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
-{
-
- if (but->flag & UI_SELECT) {
- rcti rectlink;
-
- UI_ThemeColor(TH_TEXT_HI);
-
- rectlink.xmin = BLI_rcti_cent_x(rect);
- rectlink.ymin = BLI_rcti_cent_y(rect);
- rectlink.xmax = but->linkto[0];
- rectlink.ymax = but->linkto[1];
-
- ui_draw_link_bezier(&rectlink);
- }
-}
-
static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
uiWidgetBase wtb, wtb1;
rcti rect1;
- double value;
- float offs, toffs, fac = 0;
+ float offs, toffs;
char outline[3];
widget_init(&wtb);
widget_init(&wtb1);
- /* backdrop first */
-
- /* fully rounded */
- offs = 0.5f * BLI_rcti_size_y(rect);
+ /* Backdrop first. */
+ offs = wcol->roundness * BLI_rcti_size_y(rect);
toffs = offs * 0.75f;
round_box_edges(&wtb, roundboxalign, rect, offs);
wtb.draw_outline = false;
widgetbase_draw(&wtb, wcol);
- /* draw left/right parts only when not in text editing */
+ /* Draw slider part only when not in text editing. */
if (!(state & UI_STATE_TEXT_INPUT)) {
- int roundboxalign_slider;
+ int roundboxalign_slider = roundboxalign;
- /* slider part */
copy_v3_v3_char(outline, wcol->outline);
copy_v3_v3_char(wcol->outline, wcol->item);
copy_v3_v3_char(wcol->inner, wcol->item);
- if (!(state & UI_SELECT))
+ if (!(state & UI_SELECT)) {
SWAP(short, wcol->shadetop, wcol->shadedown);
+ }
rect1 = *rect;
+ float factor, factor_ui;
+ float factor_discard = 1.0f; /* No discard. */
+ float value = (float)ui_but_value_get(but);
- value = ui_but_value_get(but);
- if ((but->softmax - but->softmin) > 0) {
- fac = ((float)value - but->softmin) * (BLI_rcti_size_x(&rect1) - offs) / (but->softmax - but->softmin);
+ if (but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PERCENTAGE)) {
+ factor = value / but->softmax;
+ }
+ else {
+ factor = (value - but->softmin) / (but->softmax - but->softmin);
}
- /* left part of slider, always rounded */
- rect1.xmax = rect1.xmin + ceil(offs + U.pixelsize);
- round_box_edges(&wtb1, roundboxalign & ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT), &rect1, offs);
- wtb1.draw_outline = false;
- widgetbase_draw(&wtb1, wcol);
-
- /* right part of slider, interpolate roundness */
- rect1.xmax = rect1.xmin + fac + offs;
- rect1.xmin += floor(offs - U.pixelsize);
+ float width = (float)BLI_rcti_size_x(rect);
+ factor_ui = factor * width;
- if (rect1.xmax + offs > rect->xmax) {
- roundboxalign_slider = roundboxalign & ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
- offs *= (rect1.xmax + offs - rect->xmax) / offs;
+ if (factor_ui <= offs) {
+ /* Left part only. */
+ roundboxalign_slider &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
+ rect1.xmax = rect1.xmin + offs;
+ factor_discard = factor_ui / offs;
+ }
+ else if (factor_ui <= width - offs) {
+ /* Left part + middle part. */
+ roundboxalign_slider &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
+ rect1.xmax = rect1.xmin + factor_ui;
}
else {
- roundboxalign_slider = 0;
- offs = 0.0f;
+ /* Left part + middle part + right part. */
+ factor_discard = factor;
}
- round_box_edges(&wtb1, roundboxalign_slider, &rect1, offs);
+ round_box_edges(&wtb1, roundboxalign_slider, &rect1, offs);
+ wtb1.draw_outline = false;
+ widgetbase_set_uniform_discard_factor(&wtb1, factor_discard);
widgetbase_draw(&wtb1, wcol);
+
copy_v3_v3_char(wcol->outline, outline);
- if (!(state & UI_SELECT))
+ if (!(state & UI_SELECT)) {
SWAP(short, wcol->shadetop, wcol->shadedown);
+ }
}
- /* outline */
+ /* Outline. */
wtb.draw_outline = true;
wtb.draw_inner = false;
widgetbase_draw(&wtb, wcol);
- /* add space at either side of the button so text aligns with numbuttons (which have arrow icons) */
+ /* Add space at either side of the button so text aligns with numbuttons (which have arrow icons). */
if (!(state & UI_STATE_TEXT_INPUT)) {
rect->xmax -= toffs;
rect->xmin += toffs;
@@ -3077,13 +3352,12 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
widget_init(&wtb);
- /* half rounded */
- rad = 0.25f * U.widget_unit;
+ rad = wcol->roundness * U.widget_unit;
round_box_edges(&wtb, roundboxalign, rect, rad);
ui_but_v3_get(but, col);
- if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
+ if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_OVERRIDEN | UI_BUT_REDALERT)) {
/* draw based on state - color for keyed etc */
widgetbase_draw(&wtb, wcol);
@@ -3114,7 +3388,6 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
}
widgetbase_draw(&wtb, wcol);
-
if (but->a1 == UI_PALETTE_COLOR && ((Palette *)but->rnapoin.id.data)->active_color == (int)but->a2) {
float width = rect->xmax - rect->xmin;
float height = rect->ymax - rect->ymin;
@@ -3123,12 +3396,22 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
bw += (bw < 0.5f) ? 0.5f : -0.5f;
- glColor4f(bw, bw, bw, 1.0);
- glBegin(GL_TRIANGLES);
- glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.9f * height);
- glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.5f * height);
- glVertex2f(rect->xmin + 0.5f * width, rect->ymin + 0.9f * height);
- glEnd();
+ /* We are drawing on top of widget bases. Flush cache. */
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
+
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3f(bw, bw, bw);
+ immBegin(GWN_PRIM_TRIS, 3);
+ immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.9f * height);
+ immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.5f * height);
+ immVertex2f(pos, rect->xmin + 0.5f * width, rect->ymin + 0.9f * height);
+ immEnd();
+
+ immUnbindProgram();
}
}
@@ -3146,8 +3429,7 @@ static void widget_icon_has_anim(uiBut *but, uiWidgetColors *wcol, rcti *rect, i
widget_init(&wtb);
wtb.draw_outline = false;
- /* rounded */
- rad = 0.5f * BLI_rcti_size_y(rect);
+ rad = wcol->roundness * BLI_rcti_size_y(rect);
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
widgetbase_draw(&wtb, wcol);
}
@@ -3169,8 +3451,7 @@ static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roun
widget_init(&wtb);
- /* half rounded */
- rad = 0.2f * U.widget_unit;
+ rad = wcol->roundness * U.widget_unit;
round_box_edges(&wtb, roundboxalign, rect, rad);
widgetbase_draw(&wtb, wcol);
@@ -3184,12 +3465,13 @@ static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
widget_init(&wtb);
- /* half rounded */
- rad = 0.2f * U.widget_unit;
+ rad = wcol->roundness * U.widget_unit;
round_box_edges(&wtb, roundboxalign, rect, rad);
/* decoration */
shape_preset_trias_from_rect_menu(&wtb.tria1, rect);
+ /* copy size and center to 2nd tria */
+ wtb.tria2 = wtb.tria1;
widgetbase_draw(&wtb, wcol);
@@ -3204,44 +3486,31 @@ static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(stat
widget_init(&wtb);
- /* half rounded */
- rad = 0.2f * U.widget_unit;
- round_box_edges(&wtb, roundboxalign, rect, rad);
-
- /* decoration */
- widgetbase_draw(&wtb, wcol);
-}
-
-static void widget_menunodebut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
-{
- /* silly node link button hacks */
- uiWidgetBase wtb;
- uiWidgetColors wcol_backup = *wcol;
- float rad;
-
- widget_init(&wtb);
-
- /* half rounded */
- rad = 0.2f * U.widget_unit;
+ rad = wcol->roundness * U.widget_unit;
round_box_edges(&wtb, roundboxalign, rect, rad);
- wcol->inner[0] = min_ii(wcol->inner[0] + 15, 255);
- wcol->inner[1] = min_ii(wcol->inner[1] + 15, 255);
- wcol->inner[2] = min_ii(wcol->inner[2] + 15, 255);
- wcol->outline[0] = min_ii(wcol->outline[0] + 15, 255);
- wcol->outline[1] = min_ii(wcol->outline[1] + 15, 255);
- wcol->outline[2] = min_ii(wcol->outline[2] + 15, 255);
-
/* decoration */
widgetbase_draw(&wtb, wcol);
- *wcol = wcol_backup;
}
static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
- if (state & UI_ACTIVE) {
+ float back[4];
+ UI_GetThemeColor4fv(TH_BACK, back);
+
+ if ((state & UI_ACTIVE) || (back[3] < 1.0f)) {
uiWidgetBase wtb;
- const float rad = 0.2f * U.widget_unit;
+ const float rad = wcol->roundness * U.widget_unit;
+
+ if (state & UI_ACTIVE) {
+ copy_v4_v4_char(wcol->inner, wcol->inner_sel);
+ copy_v3_v3_char(wcol->text, wcol->text_sel);
+ copy_v3_v3_char(wcol->outline, wcol->inner);
+ }
+ else {
+ wcol->inner[3] *= 1.0f - back[3];
+ wcol->outline[3] = 0.0f;
+ }
widget_init(&wtb);
@@ -3275,7 +3544,7 @@ static void widget_menu_radial_itembut(uiBut *but, uiWidgetColors *wcol, rcti *r
wtb.draw_emboss = false;
- rad = 0.5f * BLI_rcti_size_y(rect);
+ rad = wcol->roundness * BLI_rcti_size_y(rect);
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
wcol->inner[3] *= fac;
@@ -3295,9 +3564,9 @@ static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(sta
widget_init(&wtb);
- /* rounded, but no outline */
+ /* no outline */
wtb.draw_outline = false;
- rad = 0.2f * U.widget_unit;
+ rad = wcol->roundness * U.widget_unit;
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
widgetbase_draw(&wtb, wcol);
@@ -3322,8 +3591,7 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN
recttemp.xmax -= delta;
recttemp.ymax -= delta;
- /* half rounded */
- rad = BLI_rcti_size_y(&recttemp) / 3;
+ rad = wcol->roundness * BLI_rcti_size_y(&recttemp);
round_box_edges(&wtb, UI_CNR_ALL, &recttemp, rad);
/* decoration */
@@ -3364,8 +3632,7 @@ static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
widget_init(&wtb);
- /* half rounded */
- rad = 0.2f * U.widget_unit;
+ rad = wcol->roundness * U.widget_unit;
round_box_edges(&wtb, roundboxalign, rect, rad);
widgetbase_draw(&wtb, wcol);
@@ -3388,8 +3655,7 @@ static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(
wcol->inner[2] = but->col[2];
}
- /* half rounded */
- rad = 0.2f * U.widget_unit;
+ rad = wcol->roundness * U.widget_unit;
round_box_edges(&wtb, roundboxalign, rect, rad);
widgetbase_draw(&wtb, wcol);
@@ -3404,8 +3670,7 @@ static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int
widget_init(&wtb);
- /* half rounded */
- rad = 0.2f * U.widget_unit;
+ rad = wcol->roundness * U.widget_unit;
round_box_edges(&wtb, roundboxalign, rect, rad);
widgetbase_draw(&wtb, wcol);
@@ -3415,7 +3680,7 @@ static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int
static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
uiWidgetBase wtb;
- const float rad = 0.25f * U.widget_unit;
+ const float rad = wcol->roundness * U.widget_unit;
widget_init(&wtb);
@@ -3429,7 +3694,7 @@ static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
static void widget_roundbut_exec(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
uiWidgetBase wtb;
- const float rad = 0.25f * U.widget_unit;
+ const float rad = wcol->roundness * U.widget_unit;
widget_init(&wtb);
@@ -3444,10 +3709,68 @@ static void widget_roundbut_exec(uiWidgetColors *wcol, rcti *rect, int state, in
widgetbase_draw(&wtb, wcol);
}
+static void widget_tab(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+{
+ const uiStyle *style = UI_style_get();
+ const float rad = wcol->roundness * U.widget_unit;
+ const int fontid = style->widget.uifont_id;
+ const bool is_active = (state & UI_SELECT);
+
+/* Draw shaded outline - Disabled for now, seems incorrect and also looks nicer without it imho ;) */
+//#define USE_TAB_SHADED_HIGHLIGHT
+
+ uiWidgetBase wtb;
+ unsigned char theme_col_tab_highlight[3];
+
+#ifdef USE_TAB_SHADED_HIGHLIGHT
+ /* create outline highlight colors */
+ if (is_active) {
+ interp_v3_v3v3_uchar(theme_col_tab_highlight, (unsigned char *)wcol->inner_sel,
+ (unsigned char *)wcol->outline, 0.2f);
+ }
+ else {
+ interp_v3_v3v3_uchar(theme_col_tab_highlight, (unsigned char *)wcol->inner,
+ (unsigned char *)wcol->outline, 0.12f);
+ }
+#endif
+
+ widget_init(&wtb);
+
+ /* half rounded */
+ round_box_edges(&wtb, roundboxalign, rect, rad);
+
+ /* draw inner */
+#ifdef USE_TAB_SHADED_HIGHLIGHT
+ wtb.draw_outline = 0;
+#endif
+ widgetbase_draw(&wtb, wcol);
+
+ /* We are drawing on top of widget bases. Flush cache. */
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
+
+#ifdef USE_TAB_SHADED_HIGHLIGHT
+ /* draw outline (3d look) */
+ ui_draw_but_TAB_outline(rect, rad, theme_col_tab_highlight, (unsigned char *)wcol->inner);
+#endif
+
+ /* text shadow */
+ BLF_enable(fontid, BLF_SHADOW);
+ BLF_shadow(fontid, 3, (const float[4]){1.0f, 1.0f, 1.0f, 0.25f});
+ BLF_shadow_offset(fontid, 0, -1);
+
+#ifndef USE_TAB_SHADED_HIGHLIGHT
+ UNUSED_VARS(is_active, theme_col_tab_highlight);
+#endif
+}
+
static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
{
+ bTheme *btheme = UI_GetTheme();
+ uiWidgetColors *wcol = &btheme->tui.wcol_radio;
uiWidgetBase wtb;
- const float rad = 0.25f * U.widget_unit;
+ const float rad = wcol->roundness * U.widget_unit;
unsigned char col[4];
/* state copy! */
@@ -3459,12 +3782,17 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *
/* note: drawextra can change rect +1 or -1, to match round errors of existing previews */
but->block->drawextra(C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect);
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* make mask to draw over image */
UI_GetThemeColor3ubv(TH_BACK, col);
- glColor3ubv(col);
+ immUniformColor3ubv(col);
round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, rad);
- widgetbase_outline(&wtb);
+ widgetbase_outline(&wtb, pos);
+
+ immUnbindProgram();
}
/* outline */
@@ -3526,6 +3854,16 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.draw = widget_roundbut_exec;
break;
+ case UI_WTYPE_TOOLBAR_ITEM:
+ wt.wcol_theme = &btheme->tui.wcol_toolbar_item;
+ wt.draw = widget_roundbut_exec;
+ break;
+
+ case UI_WTYPE_TAB:
+ wt.wcol_theme = &btheme->tui.wcol_tab;
+ wt.draw = widget_tab;
+ break;
+
case UI_WTYPE_TOOLTIP:
wt.wcol_theme = &btheme->tui.wcol_tooltip;
wt.draw = widget_menu_back;
@@ -3555,6 +3893,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
break;
case UI_WTYPE_MENU_ICON_RADIO:
+ case UI_WTYPE_MENU_NODE_LINK:
wt.wcol_theme = &btheme->tui.wcol_menu;
wt.draw = widget_menuiconbut;
break;
@@ -3564,11 +3903,6 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.draw = widget_menubut;
break;
- case UI_WTYPE_MENU_NODE_LINK:
- wt.wcol_theme = &btheme->tui.wcol_menu;
- wt.draw = widget_menunodebut;
- break;
-
case UI_WTYPE_PULLDOWN:
wt.wcol_theme = &btheme->tui.wcol_pulldown;
wt.draw = widget_pulldownbut;
@@ -3648,7 +3982,7 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
/* alignment */
if ((but->drawflag & UI_BUT_ALIGN) && but->type != UI_BTYPE_PULLDOWN) {
- /* ui_block_position has this correction too, keep in sync */
+ /* ui_popup_block_position has this correction too, keep in sync */
if (but->drawflag & (UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_STITCH_TOP))
rect->ymax += U.pixelsize;
if (but->drawflag & (UI_BUT_ALIGN_LEFT | UI_BUT_ALIGN_STITCH_LEFT))
@@ -3686,7 +4020,7 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
}
/* align with open menu */
- if (but->active) {
+ if (but->active && (but->type != UI_BTYPE_POPOVER)) {
int direction = ui_but_menu_direction(but);
if (direction == UI_DIR_UP) roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_TOP_LEFT);
@@ -3710,6 +4044,10 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
uiFontStyle *fstyle = &style->widget;
uiWidgetType *wt = NULL;
+#ifdef USE_UI_POPOVER_ONCE
+ const rcti rect_orig = *rect;
+#endif
+
/* handle menus separately */
if (but->dt == UI_EMBOSS_PULLDOWN) {
switch (but->type) {
@@ -3757,10 +4095,20 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
case UI_BTYPE_SEPR:
case UI_BTYPE_SEPR_LINE:
+ case UI_BTYPE_SEPR_SPACER:
break;
case UI_BTYPE_BUT:
+#ifdef USE_UI_TOOLBAR_HACK
+ if (UI_but_is_tool(but)) {
+ wt = widget_type(UI_WTYPE_TOOLBAR_ITEM);
+ }
+ else {
+ wt = widget_type(UI_WTYPE_EXEC);
+ }
+#else
wt = widget_type(UI_WTYPE_EXEC);
+#endif
break;
case UI_BTYPE_NUM:
@@ -3789,6 +4137,10 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
wt->wcol_theme = &btheme->tui.wcol_menu_back;
break;
+ case UI_BTYPE_TAB:
+ wt = widget_type(UI_WTYPE_TAB);
+ break;
+
case UI_BTYPE_BUT_TOGGLE:
case UI_BTYPE_TOGGLE:
case UI_BTYPE_TOGGLE_N:
@@ -3812,6 +4164,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
case UI_BTYPE_MENU:
case UI_BTYPE_BLOCK:
+ case UI_BTYPE_POPOVER:
if (but->flag & UI_BUT_NODE_LINK) {
/* new node-link button, not active yet XXX */
wt = widget_type(UI_WTYPE_MENU_NODE_LINK);
@@ -3851,13 +4204,6 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
wt = widget_type(UI_WTYPE_BOX);
break;
- case UI_BTYPE_LINK:
- case UI_BTYPE_INLINK:
- wt = widget_type(UI_WTYPE_ICON);
- wt->custom = widget_link;
-
- break;
-
case UI_BTYPE_EXTRA:
widget_draw_extra_mask(C, but, widget_type(UI_WTYPE_BOX), rect);
break;
@@ -3954,6 +4300,15 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
state |= UI_STATE_HOLD_ACTION;
}
+ if (state & UI_ACTIVE) {
+ if (but->drawflag & UI_BUT_ACTIVE_LEFT) {
+ state |= UI_STATE_ACTIVE_LEFT;
+ }
+ else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) {
+ state |= UI_STATE_ACTIVE_RIGHT;
+ }
+ }
+
if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
if (but->dt != UI_EMBOSS_PULLDOWN)
disabled = true;
@@ -3968,10 +4323,29 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
wt->draw(&wt->wcol, rect, state, roundboxalign);
if (disabled)
- glEnable(GL_BLEND);
+ GPU_blend(true);
+
+#ifdef USE_UI_POPOVER_ONCE
+ if (but->block->flag & UI_BLOCK_POPOVER_ONCE) {
+ if ((state & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) {
+ uiWidgetType wt_back = *wt;
+ uiWidgetType *wt_temp = widget_type(UI_WTYPE_MENU_ITEM);
+ wt_temp->state(wt_temp, state);
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
+ wt->wcol.inner[3] = 128;
+ wt->wcol.roundness = 0.5f;
+ ui_draw_roundbox(
+ &rect_orig,
+ 0.25f * min_ff(BLI_rcti_size_x(&rect_orig), BLI_rcti_size_y(&rect_orig)),
+ &wt_temp->wcol);
+ *wt = wt_back;
+ }
+ }
+#endif
+
wt->text(fstyle, &wt->wcol, but, rect);
if (disabled)
- glDisable(GL_BLEND);
+ GPU_blend(false);
// if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
// if (but->dt != UI_EMBOSS_PULLDOWN)
@@ -3979,6 +4353,28 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
}
}
+static void ui_draw_clip_tri(uiBlock *block, rcti *rect, uiWidgetType *wt)
+{
+ if (block) {
+ float draw_color[4];
+ unsigned char *color = (unsigned char *)wt->wcol.text;
+
+ draw_color[0] = ((float)color[0]) / 255.0f;
+ draw_color[1] = ((float)color[1]) / 255.0f;
+ draw_color[2] = ((float)color[2]) / 255.0f;
+ draw_color[3] = 1.0f;
+
+ if (block->flag & UI_BLOCK_CLIPTOP) {
+ /* XXX no scaling for UI here yet */
+ UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't', draw_color);
+ }
+ if (block->flag & UI_BLOCK_CLIPBOTTOM) {
+ /* XXX no scaling for UI here yet */
+ UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v', draw_color);
+ }
+ }
+}
+
void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
{
uiWidgetType *wt = widget_type(UI_WTYPE_MENU_BACK);
@@ -3989,18 +4385,79 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
else
wt->draw(&wt->wcol, rect, 0, 0);
- if (block) {
- if (block->flag & UI_BLOCK_CLIPTOP) {
- /* XXX no scaling for UI here yet */
- glColor3ubv((unsigned char *)wt->wcol.text);
- UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't');
+ ui_draw_clip_tri(block, rect, wt);
+}
+
+/**
+ * Similar to 'widget_menu_back', however we can't use the widget preset system
+ * because we need to pass in the original location so we know where to show the arrow.
+ */
+static void ui_draw_popover_back_impl(
+ const uiWidgetColors *wcol, rcti *rect, int direction, const float unit_size,
+ const float mval_origin[2])
+{
+ /* tsk, this isn't nice. */
+ const float unit_half = unit_size / 2;
+ const float cent_x = mval_origin ? mval_origin[0] : BLI_rcti_cent_x(rect);
+ rect->ymax -= unit_half;
+ rect->ymin += unit_half;
+
+ GPU_blend(true);
+
+ /* Extracted from 'widget_menu_back', keep separate to avoid menu changes breaking popovers */
+ {
+ uiWidgetBase wtb;
+ widget_init(&wtb);
+
+ const int roundboxalign = UI_CNR_ALL;
+ widget_softshadow(rect, roundboxalign, wcol->roundness * U.widget_unit);
+
+ round_box_edges(&wtb, roundboxalign, rect, wcol->roundness * U.widget_unit);
+ wtb.draw_emboss = false;
+ widgetbase_draw(&wtb, wcol);
+ }
+
+ /* Draw popover arrow (top/bottom) */
+ if (ELEM(direction, UI_DIR_UP, UI_DIR_DOWN)) {
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv((unsigned char *)wcol->inner);
+ GPU_blend(true);
+ immBegin(GWN_PRIM_TRIS, 3);
+ if (direction == UI_DIR_DOWN) {
+ const float y = rect->ymax;
+ immVertex2f(pos, cent_x - unit_half, y);
+ immVertex2f(pos, cent_x + unit_half, y);
+ immVertex2f(pos, cent_x, y + unit_half);
}
- if (block->flag & UI_BLOCK_CLIPBOTTOM) {
- /* XXX no scaling for UI here yet */
- glColor3ubv((unsigned char *)wt->wcol.text);
- UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v');
+ else {
+ const float y = rect->ymin;
+ immVertex2f(pos, cent_x - unit_half, y);
+ immVertex2f(pos, cent_x + unit_half, y);
+ immVertex2f(pos, cent_x, y - unit_half);
}
+ immEnd();
+ immUnbindProgram();
+ }
+
+ GPU_blend(false);
+}
+
+void ui_draw_popover_back(ARegion *ar, uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
+{
+ uiWidgetType *wt = widget_type(UI_WTYPE_MENU_BACK);
+
+ if (block) {
+ float mval_origin[2] = {block->mx, block->my};
+ ui_window_to_block_fl(ar, block, &mval_origin[0], &mval_origin[1]);
+ ui_draw_popover_back_impl(wt->wcol_theme, rect, block->direction, U.widget_unit / block->aspect, mval_origin);
}
+ else {
+ wt->state(wt, 0);
+ wt->draw(&wt->wcol, rect, 0, 0);
+ }
+
+ ui_draw_clip_tri(block, rect, wt);
}
static void draw_disk_shaded(
@@ -4016,33 +4473,21 @@ static void draw_disk_shaded(
float y1, y2;
float fac;
unsigned char r_col[4];
+ unsigned int pos, col;
- glBegin(GL_TRIANGLE_STRIP);
-
- s = sinf(start);
- c = cosf(start);
-
- y1 = s * radius_int;
- y2 = s * radius_ext;
-
+ Gwn_VertFormat *format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
if (shaded) {
- fac = (y1 + radius_ext) * radius_ext_scale;
- round_box_shade_col4_r(r_col, col1, col2, fac);
-
- glColor4ubv(r_col);
+ col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
}
-
- glVertex2f(c * radius_int, s * radius_int);
-
- if (shaded) {
- fac = (y2 + radius_ext) * radius_ext_scale;
- round_box_shade_col4_r(r_col, col1, col2, fac);
-
- glColor4ubv(r_col);
+ else {
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv((unsigned char *)col1);
}
- glVertex2f(c * radius_ext, s * radius_ext);
- for (i = 1; i < subd; i++) {
+ immBegin(GWN_PRIM_TRI_STRIP, subd * 2);
+ for (i = 0; i < subd; i++) {
float a;
a = start + ((i) / (float)(subd - 1)) * angle;
@@ -4054,20 +4499,20 @@ static void draw_disk_shaded(
if (shaded) {
fac = (y1 + radius_ext) * radius_ext_scale;
round_box_shade_col4_r(r_col, col1, col2, fac);
-
- glColor4ubv(r_col);
+ immAttrib4ubv(col, r_col);
}
- glVertex2f(c * radius_int, s * radius_int);
+ immVertex2f(pos, c * radius_int, s * radius_int);
if (shaded) {
fac = (y2 + radius_ext) * radius_ext_scale;
round_box_shade_col4_r(r_col, col1, col2, fac);
-
- glColor4ubv(r_col);
+ immAttrib4ubv(col, r_col);
}
- glVertex2f(c * radius_ext, s * radius_ext);
+ immVertex2f(pos, c * radius_ext, s * radius_ext);
}
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
void ui_draw_pie_center(uiBlock *block)
@@ -4086,18 +4531,17 @@ void ui_draw_pie_center(uiBlock *block)
float angle = atan2f(pie_dir[1], pie_dir[0]);
float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_2 : M_PI_4;
- glPushMatrix();
- glTranslatef(cx, cy, 0.0f);
+ gpuPushMatrix();
+ gpuTranslate2f(cx, cy);
- glEnable(GL_BLEND);
+ GPU_blend(true);
if (btheme->tui.wcol_pie_menu.shaded) {
char col1[4], col2[4];
shadecolors4(col1, col2, btheme->tui.wcol_pie_menu.inner, btheme->tui.wcol_pie_menu.shadetop, btheme->tui.wcol_pie_menu.shadedown);
draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, col1, col2, true);
}
else {
- glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.inner);
- draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, NULL, NULL, false);
+ draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, btheme->tui.wcol_pie_menu.inner, NULL, false);
}
if (!(block->pie_data.flags & UI_PIE_INVALID_DIR)) {
@@ -4107,25 +4551,34 @@ void ui_draw_pie_center(uiBlock *block)
draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, col1, col2, true);
}
else {
- glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.inner_sel);
- draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, NULL, NULL, false);
+ draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, btheme->tui.wcol_pie_menu.inner_sel, NULL, false);
}
}
- glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.outline);
- glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_internal, subd);
- glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_external, subd);
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv((unsigned char *)btheme->tui.wcol_pie_menu.outline);
+
+ imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_internal, subd);
+ imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_external, subd);
+
+ immUnbindProgram();
if (U.pie_menu_confirm > 0 && !(block->pie_data.flags & (UI_PIE_INVALID_DIR | UI_PIE_CLICK_STYLE))) {
float pie_confirm_radius = U.pixelsize * (pie_radius_internal + U.pie_menu_confirm);
float pie_confirm_external = U.pixelsize * (pie_radius_internal + U.pie_menu_confirm + 7.0f);
- glColor4ub(btheme->tui.wcol_pie_menu.text_sel[0], btheme->tui.wcol_pie_menu.text_sel[1], btheme->tui.wcol_pie_menu.text_sel[2], 64);
- draw_disk_shaded(angle - range / 2.0f, range, pie_confirm_radius, pie_confirm_external, subd, NULL, NULL, false);
+ const char col[4] = {btheme->tui.wcol_pie_menu.text_sel[0],
+ btheme->tui.wcol_pie_menu.text_sel[1],
+ btheme->tui.wcol_pie_menu.text_sel[2],
+ 64};
+
+ draw_disk_shaded(angle - range / 2.0f, range, pie_confirm_radius, pie_confirm_external, subd, col, NULL, false);
}
- glDisable(GL_BLEND);
- glPopMatrix();
+ GPU_blend(false);
+ gpuPopMatrix();
}
@@ -4135,30 +4588,42 @@ uiWidgetColors *ui_tooltip_get_theme(void)
return wt->wcol_theme;
}
-void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect)
+/**
+ * Generic drawing for background.
+ */
+void ui_draw_widget_back_color(
+ uiWidgetTypeEnum type, bool use_shadow, const rcti *rect,
+ const float color[4])
{
- uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP);
+ uiWidgetType *wt = widget_type(type);
+
+ if (use_shadow) {
+ GPU_blend(true);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit);
+ GPU_blend(false);
+ }
+
+ rcti rect_copy = *rect;
wt->state(wt, 0);
- /* wt->draw ends up using same function to draw the tooltip as menu_back */
- wt->draw(&wt->wcol, rect, 0, 0);
+ if (color) {
+ rgba_float_to_uchar((unsigned char *)wt->wcol.inner, color);
+ }
+ wt->draw(&wt->wcol, &rect_copy, 0, UI_CNR_ALL);
}
-
-void ui_draw_search_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
+void ui_draw_widget_back(uiWidgetTypeEnum type, bool use_shadow, const rcti *rect)
{
- uiWidgetType *wt = widget_type(UI_WTYPE_BOX);
-
- glEnable(GL_BLEND);
- widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit);
- glDisable(GL_BLEND);
+ ui_draw_widget_back_color(type, use_shadow, rect, NULL);
+}
+void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect)
+{
+ uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP);
wt->state(wt, 0);
- if (block)
- wt->draw(&wt->wcol, rect, block->flag, UI_CNR_ALL);
- else
- wt->draw(&wt->wcol, rect, 0, UI_CNR_ALL);
+ /* wt->draw ends up using same function to draw the tooltip as menu_back */
+ wt->draw(&wt->wcol, rect, 0, 0);
}
-
/* helper call to draw a menu item without button */
/* state: UI_ACTIVE or 0 */
void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep)
@@ -4209,8 +4674,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
}
- glColor4ubv((unsigned char *)wt->wcol.text);
- UI_fontstyle_draw(fstyle, rect, drawstr);
+ UI_fontstyle_draw(fstyle, rect, drawstr, (unsigned char *)wt->wcol.text);
}
/* part text right aligned */
@@ -4218,7 +4682,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
if (cpoin) {
fstyle->align = UI_STYLE_TEXT_RIGHT;
rect->xmax = _rect.xmax - 5;
- UI_fontstyle_draw(fstyle, rect, cpoin + 1);
+ UI_fontstyle_draw(fstyle, rect, cpoin + 1, (unsigned char *)wt->wcol.text);
*cpoin = UI_SEP_CHAR;
}
}
@@ -4234,9 +4698,9 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
height = ICON_SIZE_FROM_BUTRECT(rect);
aspect = ICON_DEFAULT_HEIGHT / height;
- glEnable(GL_BLEND);
+ GPU_blend(true);
UI_icon_draw_aspect(xs, ys, iconid, aspect, 1.0f); /* XXX scale weak get from fstyle? */
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
}
@@ -4253,9 +4717,9 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int
/* draw icon in rect above the space reserved for the label */
rect->ymin += text_size;
- glEnable(GL_BLEND);
+ GPU_blend(true);
widget_draw_preview(iconid, 1.0f, rect);
- glDisable(GL_BLEND);
+ GPU_blend(false);
BLF_width_and_height(fstyle->uifont_id, name, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]);
@@ -4276,8 +4740,7 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int
BLI_strncpy(drawstr, name, sizeof(drawstr));
UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
- glColor4ubv((unsigned char *)wt->wcol.text);
- UI_fontstyle_draw(fstyle, &trect, drawstr);
+ UI_fontstyle_draw(fstyle, &trect, drawstr, (unsigned char *)wt->wcol.text);
}
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 77c36bf47f3..a2b1aa1f251 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -48,16 +48,24 @@
#include "BKE_addon.h"
#include "BKE_appdir.h"
#include "BKE_colorband.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "BKE_mesh_runtime.h"
#include "BIF_gl.h"
+#include "BLF_api.h"
+
+#include "ED_screen.h"
+
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "interface_intern.h"
+#include "GPU_framebuffer.h"
+
+
+extern const bTheme U_theme_default;
/* global for themes */
typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
@@ -94,6 +102,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
static char error[4] = {240, 0, 240, 255};
static char alert[4] = {240, 60, 60, 255};
static char headerdesel[4] = {0, 0, 0, 255};
+ static char back[4] = {0, 0, 0, 255};
static char setting = 0;
const char *cp = error;
@@ -154,18 +163,18 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case SPACE_CONSOLE:
ts = &btheme->tconsole;
break;
- case SPACE_TIME:
- ts = &btheme->ttime;
- break;
case SPACE_NODE:
ts = &btheme->tnode;
break;
- case SPACE_LOGIC:
- ts = &btheme->tlogic;
- break;
case SPACE_CLIP:
ts = &btheme->tclip;
break;
+ case SPACE_TOPBAR:
+ ts = &btheme->ttopbar;
+ break;
+ case SPACE_STATUSBAR:
+ ts = &btheme->tstatusbar;
+ break;
default:
ts = &btheme->tv3d;
break;
@@ -181,6 +190,12 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->header;
else
cp = ts->button;
+
+ copy_v4_v4_char(back, cp);
+ if (!ED_region_is_overlap(spacetype, theme_regionid)) {
+ back[3] = 255;
+ }
+ cp = back;
break;
case TH_LOW_GRAD:
cp = ts->gradients.gradient;
@@ -231,6 +246,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
headerdesel[0] = cp[0] > 10 ? cp[0] - 10 : 0;
headerdesel[1] = cp[1] > 10 ? cp[1] - 10 : 0;
headerdesel[2] = cp[2] > 10 ? cp[2] - 10 : 0;
+ headerdesel[3] = cp[3];
cp = headerdesel;
break;
case TH_HEADER_TEXT:
@@ -242,14 +258,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->panelcolors.header; break;
case TH_PANEL_BACK:
cp = ts->panelcolors.back; break;
- case TH_PANEL_SHOW_HEADER:
- cp = &setting;
- setting = ts->panelcolors.show_header;
- break;
- case TH_PANEL_SHOW_BACK:
- cp = &setting;
- setting = ts->panelcolors.show_back;
- break;
+ case TH_PANEL_SUB_BACK:
+ cp = ts->panelcolors.sub_back; break;
case TH_BUTBACK:
cp = ts->button; break;
@@ -659,6 +669,9 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_WIDGET_EMBOSS:
cp = btheme->tui.widget_emboss; break;
+ case TH_EDITOR_OUTLINE:
+ cp = btheme->tui.editor_outline;
+ break;
case TH_AXIS_X:
cp = btheme->tui.xaxis; break;
case TH_AXIS_Y:
@@ -666,6 +679,17 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_AXIS_Z:
cp = btheme->tui.zaxis; break;
+ case TH_MANIPULATOR_HI:
+ cp = btheme->tui.manipulator_hi; break;
+ case TH_MANIPULATOR_PRIMARY:
+ cp = btheme->tui.manipulator_primary; break;
+ case TH_MANIPULATOR_SECONDARY:
+ cp = btheme->tui.manipulator_secondary; break;
+ case TH_MANIPULATOR_A:
+ cp = btheme->tui.manipulator_a; break;
+ case TH_MANIPULATOR_B:
+ cp = btheme->tui.manipulator_b; break;
+
case TH_INFO_SELECTED:
cp = ts->info_selected;
break;
@@ -706,136 +730,6 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
return (const unsigned char *)cp;
}
-/* use this call to init new bone color sets in Theme */
-static void ui_theme_init_boneColorSets(bTheme *btheme)
-{
- int i;
-
- /* define default color sets - currently we only define 15 of these, though that should be ample */
- /* set 1 */
- rgba_char_args_set(btheme->tarm[0].solid, 0x9a, 0x00, 0x00, 255);
- rgba_char_args_set(btheme->tarm[0].select, 0xbd, 0x11, 0x11, 255);
- rgba_char_args_set(btheme->tarm[0].active, 0xf7, 0x0a, 0x0a, 255);
- /* set 2 */
- rgba_char_args_set(btheme->tarm[1].solid, 0xf7, 0x40, 0x18, 255);
- rgba_char_args_set(btheme->tarm[1].select, 0xf6, 0x69, 0x13, 255);
- rgba_char_args_set(btheme->tarm[1].active, 0xfa, 0x99, 0x00, 255);
- /* set 3 */
- rgba_char_args_set(btheme->tarm[2].solid, 0x1e, 0x91, 0x09, 255);
- rgba_char_args_set(btheme->tarm[2].select, 0x59, 0xb7, 0x0b, 255);
- rgba_char_args_set(btheme->tarm[2].active, 0x83, 0xef, 0x1d, 255);
- /* set 4 */
- rgba_char_args_set(btheme->tarm[3].solid, 0x0a, 0x36, 0x94, 255);
- rgba_char_args_set(btheme->tarm[3].select, 0x36, 0x67, 0xdf, 255);
- rgba_char_args_set(btheme->tarm[3].active, 0x5e, 0xc1, 0xef, 255);
- /* set 5 */
- rgba_char_args_set(btheme->tarm[4].solid, 0xa9, 0x29, 0x4e, 255);
- rgba_char_args_set(btheme->tarm[4].select, 0xc1, 0x41, 0x6a, 255);
- rgba_char_args_set(btheme->tarm[4].active, 0xf0, 0x5d, 0x91, 255);
- /* set 6 */
- rgba_char_args_set(btheme->tarm[5].solid, 0x43, 0x0c, 0x78, 255);
- rgba_char_args_set(btheme->tarm[5].select, 0x54, 0x3a, 0xa3, 255);
- rgba_char_args_set(btheme->tarm[5].active, 0x87, 0x64, 0xd5, 255);
- /* set 7 */
- rgba_char_args_set(btheme->tarm[6].solid, 0x24, 0x78, 0x5a, 255);
- rgba_char_args_set(btheme->tarm[6].select, 0x3c, 0x95, 0x79, 255);
- rgba_char_args_set(btheme->tarm[6].active, 0x6f, 0xb6, 0xab, 255);
- /* set 8 */
- rgba_char_args_set(btheme->tarm[7].solid, 0x4b, 0x70, 0x7c, 255);
- rgba_char_args_set(btheme->tarm[7].select, 0x6a, 0x86, 0x91, 255);
- rgba_char_args_set(btheme->tarm[7].active, 0x9b, 0xc2, 0xcd, 255);
- /* set 9 */
- rgba_char_args_set(btheme->tarm[8].solid, 0xf4, 0xc9, 0x0c, 255);
- rgba_char_args_set(btheme->tarm[8].select, 0xee, 0xc2, 0x36, 255);
- rgba_char_args_set(btheme->tarm[8].active, 0xf3, 0xff, 0x00, 255);
- /* set 10 */
- rgba_char_args_set(btheme->tarm[9].solid, 0x1e, 0x20, 0x24, 255);
- rgba_char_args_set(btheme->tarm[9].select, 0x48, 0x4c, 0x56, 255);
- rgba_char_args_set(btheme->tarm[9].active, 0xff, 0xff, 0xff, 255);
- /* set 11 */
- rgba_char_args_set(btheme->tarm[10].solid, 0x6f, 0x2f, 0x6a, 255);
- rgba_char_args_set(btheme->tarm[10].select, 0x98, 0x45, 0xbe, 255);
- rgba_char_args_set(btheme->tarm[10].active, 0xd3, 0x30, 0xd6, 255);
- /* set 12 */
- rgba_char_args_set(btheme->tarm[11].solid, 0x6c, 0x8e, 0x22, 255);
- rgba_char_args_set(btheme->tarm[11].select, 0x7f, 0xb0, 0x22, 255);
- rgba_char_args_set(btheme->tarm[11].active, 0xbb, 0xef, 0x5b, 255);
- /* set 13 */
- rgba_char_args_set(btheme->tarm[12].solid, 0x8d, 0x8d, 0x8d, 255);
- rgba_char_args_set(btheme->tarm[12].select, 0xb0, 0xb0, 0xb0, 255);
- rgba_char_args_set(btheme->tarm[12].active, 0xde, 0xde, 0xde, 255);
- /* set 14 */
- rgba_char_args_set(btheme->tarm[13].solid, 0x83, 0x43, 0x26, 255);
- rgba_char_args_set(btheme->tarm[13].select, 0x8b, 0x58, 0x11, 255);
- rgba_char_args_set(btheme->tarm[13].active, 0xbd, 0x6a, 0x11, 255);
- /* set 15 */
- rgba_char_args_set(btheme->tarm[14].solid, 0x08, 0x31, 0x0e, 255);
- rgba_char_args_set(btheme->tarm[14].select, 0x1c, 0x43, 0x0b, 255);
- rgba_char_args_set(btheme->tarm[14].active, 0x34, 0x62, 0x2b, 255);
-
- /* reset flags too */
- for (i = 0; i < 20; i++)
- btheme->tarm[i].flag = 0;
-}
-
-/* use this call to init new variables in themespace, if they're same for all */
-static void ui_theme_init_new_do(ThemeSpace *ts)
-{
- rgba_char_args_set(ts->header_text, 0, 0, 0, 255);
- rgba_char_args_set(ts->header_title, 0, 0, 0, 255);
- rgba_char_args_set(ts->header_text_hi, 255, 255, 255, 255);
-
-#if 0
- rgba_char_args_set(ts->panel_text, 0, 0, 0, 255);
- rgba_char_args_set(ts->panel_title, 0, 0, 0, 255);
- rgba_char_args_set(ts->panel_text_hi, 255, 255, 255, 255);
-#endif
-
- ts->panelcolors.show_back = false;
- ts->panelcolors.show_header = false;
- rgba_char_args_set(ts->panelcolors.back, 114, 114, 114, 128);
- rgba_char_args_set(ts->panelcolors.header, 0, 0, 0, 25);
-
- rgba_char_args_set(ts->button, 145, 145, 145, 245);
- rgba_char_args_set(ts->button_title, 0, 0, 0, 255);
- rgba_char_args_set(ts->button_text, 0, 0, 0, 255);
- rgba_char_args_set(ts->button_text_hi, 255, 255, 255, 255);
-
- rgba_char_args_set(ts->list, 165, 165, 165, 255);
- rgba_char_args_set(ts->list_title, 0, 0, 0, 255);
- rgba_char_args_set(ts->list_text, 0, 0, 0, 255);
- rgba_char_args_set(ts->list_text_hi, 255, 255, 255, 255);
-
- rgba_char_args_set(ts->tab_active, 114, 114, 114, 255);
- rgba_char_args_set(ts->tab_inactive, 83, 83, 83, 255);
- rgba_char_args_set(ts->tab_back, 64, 64, 64, 255);
- rgba_char_args_set(ts->tab_outline, 60, 60, 60, 255);
-}
-
-static void ui_theme_init_new(bTheme *btheme)
-{
- ThemeSpace *ts;
-
- for (ts = UI_THEMESPACE_START(btheme); ts != UI_THEMESPACE_END(btheme); ts++) {
- ui_theme_init_new_do(ts);
- }
-}
-
-static void ui_theme_space_init_handles_color(ThemeSpace *theme_space)
-{
- rgba_char_args_set(theme_space->handle_free, 0, 0, 0, 255);
- rgba_char_args_set(theme_space->handle_auto, 0x90, 0x90, 0x00, 255);
- rgba_char_args_set(theme_space->handle_vect, 0x40, 0x90, 0x30, 255);
- rgba_char_args_set(theme_space->handle_align, 0x80, 0x30, 0x60, 255);
- rgba_char_args_set(theme_space->handle_sel_free, 0, 0, 0, 255);
- rgba_char_args_set(theme_space->handle_sel_auto, 0xf0, 0xff, 0x40, 255);
- rgba_char_args_set(theme_space->handle_sel_vect, 0x40, 0xc0, 0x30, 255);
- rgba_char_args_set(theme_space->handle_sel_align, 0xf0, 0x90, 0xa0, 255);
- rgba_char_args_set(theme_space->handle_vertex, 0x00, 0x00, 0x00, 0xff);
- rgba_char_args_set(theme_space->handle_vertex_select, 0xff, 0xff, 0, 0xff);
- rgba_char_args_set(theme_space->act_spline, 0xdb, 0x25, 0x12, 255);
-}
-
/**
* initialize default theme
* \note: when you add new colors, created & saved themes need initialized
@@ -843,370 +737,19 @@ static void ui_theme_space_init_handles_color(ThemeSpace *theme_space)
*/
void ui_theme_init_default(void)
{
- bTheme *btheme;
/* we search for the theme with name Default */
- btheme = BLI_findstring(&U.themes, "Default", offsetof(bTheme, name));
-
+ bTheme *btheme = BLI_findstring(&U.themes, "Default", offsetof(bTheme, name));
if (btheme == NULL) {
- btheme = MEM_callocN(sizeof(bTheme), "theme");
+ btheme = MEM_callocN(sizeof(bTheme), __func__);
BLI_addtail(&U.themes, btheme);
- strcpy(btheme->name, "Default");
}
UI_SetTheme(0, 0); /* make sure the global used in this file is set */
- /* UI buttons */
- ui_widget_color_init(&btheme->tui);
-
- btheme->tui.iconfile[0] = 0;
- rgba_char_args_set(btheme->tui.wcol_tooltip.text, 255, 255, 255, 255);
- rgba_char_args_set_fl(btheme->tui.widget_emboss, 1.0f, 1.0f, 1.0f, 0.02f);
-
- rgba_char_args_set(btheme->tui.xaxis, 220, 0, 0, 255);
- rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255);
- rgba_char_args_set(btheme->tui.zaxis, 0, 0, 220, 255);
-
- btheme->tui.menu_shadow_fac = 0.5f;
- btheme->tui.menu_shadow_width = 12;
-
- /* Bone Color Sets */
- ui_theme_init_boneColorSets(btheme);
-
- /* common (new) variables */
- ui_theme_init_new(btheme);
-
- /* space view3d */
- rgba_char_args_set_fl(btheme->tv3d.back, 0.225, 0.225, 0.225, 1.0);
- rgba_char_args_set(btheme->tv3d.text, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.text_hi, 255, 255, 255, 255);
-
- rgba_char_args_set_fl(btheme->tv3d.header, 0.45, 0.45, 0.45, 1.0);
- rgba_char_args_set_fl(btheme->tv3d.button, 0.45, 0.45, 0.45, 0.5);
-// rgba_char_args_set(btheme->tv3d.panel, 165, 165, 165, 127);
-
- rgba_char_args_set(btheme->tv3d.shade1, 160, 160, 160, 100);
- rgba_char_args_set(btheme->tv3d.shade2, 0x7f, 0x70, 0x70, 100);
-
- rgba_char_args_set_fl(btheme->tv3d.grid, 0.251, 0.251, 0.251, 1.0);
- rgba_char_args_set(btheme->tv3d.view_overlay, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.wire, 0x0, 0x0, 0x0, 255);
- rgba_char_args_set(btheme->tv3d.wire_edit, 0x0, 0x0, 0x0, 255);
- rgba_char_args_set(btheme->tv3d.lamp, 0, 0, 0, 40);
- rgba_char_args_set(btheme->tv3d.speaker, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.camera, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.empty, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.select, 241, 88, 0, 255);
- rgba_char_args_set(btheme->tv3d.active, 255, 170, 64, 255);
- rgba_char_args_set(btheme->tv3d.group, 8, 48, 8, 255);
- rgba_char_args_set(btheme->tv3d.group_active, 85, 187, 85, 255);
- rgba_char_args_set(btheme->tv3d.transform, 0xff, 0xff, 0xff, 255);
- rgba_char_args_set(btheme->tv3d.vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.vertex_select, 255, 133, 0, 255);
- rgba_char_args_set(btheme->tv3d.vertex_bevel, 0, 165, 255, 255);
- rgba_char_args_set(btheme->tv3d.vertex_unreferenced, 0, 0, 0, 255);
- btheme->tv3d.vertex_size = 3;
- btheme->tv3d.outline_width = 1;
- rgba_char_args_set(btheme->tv3d.edge, 0x0, 0x0, 0x0, 255);
- rgba_char_args_set(btheme->tv3d.edge_select, 255, 160, 0, 255);
- rgba_char_args_set(btheme->tv3d.edge_seam, 219, 37, 18, 255);
- rgba_char_args_set(btheme->tv3d.edge_bevel, 0, 165, 255, 255);
- rgba_char_args_set(btheme->tv3d.edge_facesel, 75, 75, 75, 255);
- rgba_char_args_set(btheme->tv3d.face, 0, 0, 0, 18);
- rgba_char_args_set(btheme->tv3d.face_select, 255, 133, 0, 60);
- rgba_char_args_set(btheme->tv3d.normal, 0x22, 0xDD, 0xDD, 255);
- rgba_char_args_set(btheme->tv3d.vertex_normal, 0x23, 0x61, 0xDD, 255);
- rgba_char_args_set(btheme->tv3d.loop_normal, 0xDD, 0x23, 0xDD, 255);
- rgba_char_args_set(btheme->tv3d.face_dot, 255, 133, 0, 255);
- rgba_char_args_set(btheme->tv3d.editmesh_active, 255, 255, 255, 128);
- rgba_char_args_set_fl(btheme->tv3d.edge_crease, 0.8, 0, 0.6, 1.0);
- rgba_char_args_set(btheme->tv3d.edge_sharp, 0, 255, 255, 255);
- rgba_char_args_set(btheme->tv3d.header_text, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.header_text_hi, 255, 255, 255, 255);
- rgba_char_args_set(btheme->tv3d.button_text, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.button_text_hi, 255, 255, 255, 255);
- rgba_char_args_set(btheme->tv3d.button_title, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.title, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.freestyle_edge_mark, 0x7f, 0xff, 0x7f, 255);
- rgba_char_args_set(btheme->tv3d.freestyle_face_mark, 0x7f, 0xff, 0x7f, 51);
- rgba_char_args_set_fl(btheme->tv3d.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
- rgba_char_args_set_fl(btheme->tv3d.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
- rgba_char_args_set(btheme->tv3d.gp_vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.gp_vertex_select, 255, 133, 0, 255);
- btheme->tv3d.gp_vertex_size = 3;
-
- btheme->tv3d.facedot_size = 4;
-
- rgba_char_args_set(btheme->tv3d.extra_edge_len, 32, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.extra_edge_angle, 32, 32, 0, 255);
- rgba_char_args_set(btheme->tv3d.extra_face_area, 0, 32, 0, 255);
- rgba_char_args_set(btheme->tv3d.extra_face_angle, 0, 0, 128, 255);
-
- rgba_char_args_set(btheme->tv3d.cframe, 0x60, 0xc0, 0x40, 255);
-
- rgba_char_args_set(btheme->tv3d.nurb_uline, 0x90, 0x90, 0x00, 255);
- rgba_char_args_set(btheme->tv3d.nurb_vline, 0x80, 0x30, 0x60, 255);
- rgba_char_args_set(btheme->tv3d.nurb_sel_uline, 0xf0, 0xff, 0x40, 255);
- rgba_char_args_set(btheme->tv3d.nurb_sel_vline, 0xf0, 0x90, 0xa0, 255);
-
- ui_theme_space_init_handles_color(&btheme->tv3d);
-
- rgba_char_args_set(btheme->tv3d.act_spline, 0xdb, 0x25, 0x12, 255);
- rgba_char_args_set(btheme->tv3d.lastsel_point, 0xff, 0xff, 0xff, 255);
-
- rgba_char_args_set(btheme->tv3d.bone_solid, 200, 200, 200, 255);
- /* alpha 80 is not meant editable, used for wire+action draw */
- rgba_char_args_set(btheme->tv3d.bone_pose, 80, 200, 255, 80);
- rgba_char_args_set(btheme->tv3d.bone_pose_active, 140, 255, 255, 80);
-
- rgba_char_args_set(btheme->tv3d.bundle_solid, 200, 200, 200, 255);
- rgba_char_args_set(btheme->tv3d.camera_path, 0x00, 0x00, 0x00, 255);
-
- rgba_char_args_set(btheme->tv3d.skin_root, 180, 77, 77, 255);
- rgba_char_args_set(btheme->tv3d.gradients.gradient, 0, 0, 0, 0);
- rgba_char_args_set(btheme->tv3d.gradients.high_gradient, 58, 58, 58, 255);
- btheme->tv3d.gradients.show_grad = false;
-
- rgba_char_args_set(btheme->tv3d.clipping_border_3d, 50, 50, 50, 255);
-
- rgba_char_args_set(btheme->tv3d.time_keyframe, 0xDD, 0xD7, 0x00, 0xFF);
- rgba_char_args_set(btheme->tv3d.time_gp_keyframe, 0xB5, 0xE6, 0x1D, 0xFF);
-
- /* space buttons */
- /* to have something initialized */
- btheme->tbuts = btheme->tv3d;
-
- rgba_char_args_set_fl(btheme->tbuts.back, 0.45, 0.45, 0.45, 1.0);
-// rgba_char_args_set(btheme->tbuts.panel, 0x82, 0x82, 0x82, 255);
-
- /* graph editor */
- btheme->tipo = btheme->tv3d;
- rgba_char_args_set_fl(btheme->tipo.back, 0.42, 0.42, 0.42, 1.0);
- rgba_char_args_set_fl(btheme->tipo.list, 0.4, 0.4, 0.4, 1.0);
- rgba_char_args_set(btheme->tipo.grid, 94, 94, 94, 255);
-// rgba_char_args_set(btheme->tipo.panel, 255, 255, 255, 150);
- rgba_char_args_set(btheme->tipo.shade1, 150, 150, 150, 100); /* scrollbars */
- rgba_char_args_set(btheme->tipo.shade2, 0x70, 0x70, 0x70, 100);
- rgba_char_args_set(btheme->tipo.vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tipo.vertex_select, 255, 133, 0, 255);
- rgba_char_args_set(btheme->tipo.hilite, 0x60, 0xc0, 0x40, 255);
- btheme->tipo.vertex_size = 6;
-
- rgba_char_args_set(btheme->tipo.handle_vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tipo.handle_vertex_select, 255, 133, 0, 255);
- rgba_char_args_set(btheme->tipo.handle_auto_clamped, 0x99, 0x40, 0x30, 255);
- rgba_char_args_set(btheme->tipo.handle_sel_auto_clamped, 0xf0, 0xaf, 0x90, 255);
- btheme->tipo.handle_vertex_size = 5;
-
- rgba_char_args_set(btheme->tipo.ds_channel, 82, 96, 110, 255);
- rgba_char_args_set(btheme->tipo.ds_subchannel, 124, 137, 150, 255);
- rgba_char_args_set(btheme->tipo.group, 79, 101, 73, 255);
- rgba_char_args_set(btheme->tipo.group_active, 135, 177, 125, 255);
-
- /* dopesheet */
- btheme->tact = btheme->tipo;
- rgba_char_args_set(btheme->tact.strip, 12, 10, 10, 128);
- rgba_char_args_set(btheme->tact.strip_select, 255, 140, 0, 255);
-
- rgba_char_args_set(btheme->tact.anim_active, 204, 112, 26, 102);
-
- rgba_char_args_set(btheme->tact.keytype_keyframe, 232, 232, 232, 255);
- rgba_char_args_set(btheme->tact.keytype_keyframe_select, 255, 190, 50, 255);
- rgba_char_args_set(btheme->tact.keytype_extreme, 232, 179, 204, 255);
- rgba_char_args_set(btheme->tact.keytype_extreme_select, 242, 128, 128, 255);
- rgba_char_args_set(btheme->tact.keytype_breakdown, 179, 219, 232, 255);
- rgba_char_args_set(btheme->tact.keytype_breakdown_select, 84, 191, 237, 255);
- rgba_char_args_set(btheme->tact.keytype_jitter, 148, 229, 117, 255);
- rgba_char_args_set(btheme->tact.keytype_jitter_select, 97, 192, 66, 255);
-
- rgba_char_args_set(btheme->tact.keyborder, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tact.keyborder_select, 0, 0, 0, 255);
-
- btheme->tact.keyframe_scale_fac = 1.0f;
-
- /* space nla */
- btheme->tnla = btheme->tact;
-
- rgba_char_args_set(btheme->tnla.anim_active, 204, 112, 26, 102); /* same as for dopesheet; duplicate here for easier reference */
- rgba_char_args_set(btheme->tnla.anim_non_active, 153, 135, 97, 77);
-
- rgba_char_args_set(btheme->tnla.nla_tweaking, 77, 243, 26, 77);
- rgba_char_args_set(btheme->tnla.nla_tweakdupli, 217, 0, 0, 255);
-
- rgba_char_args_set(btheme->tnla.nla_transition, 28, 38, 48, 255);
- rgba_char_args_set(btheme->tnla.nla_transition_sel, 46, 117, 219, 255);
- rgba_char_args_set(btheme->tnla.nla_meta, 51, 38, 66, 255);
- rgba_char_args_set(btheme->tnla.nla_meta_sel, 105, 33, 150, 255);
- rgba_char_args_set(btheme->tnla.nla_sound, 43, 61, 61, 255);
- rgba_char_args_set(btheme->tnla.nla_sound_sel, 31, 122, 122, 255);
-
- rgba_char_args_set(btheme->tnla.keyborder, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tnla.keyborder_select, 0, 0, 0, 255);
-
- /* space file */
- /* to have something initialized */
- btheme->tfile = btheme->tv3d;
- rgba_char_args_set_fl(btheme->tfile.back, 0.3, 0.3, 0.3, 1);
-// rgba_char_args_set_fl(btheme->tfile.panel, 0.3, 0.3, 0.3, 1);
- rgba_char_args_set_fl(btheme->tfile.list, 0.4, 0.4, 0.4, 1);
- rgba_char_args_set(btheme->tfile.text, 250, 250, 250, 255);
- rgba_char_args_set(btheme->tfile.text_hi, 15, 15, 15, 255);
-// rgba_char_args_set(btheme->tfile.panel, 145, 145, 145, 255); /* bookmark/ui regions */
- rgba_char_args_set(btheme->tfile.hilite, 255, 140, 25, 255); /* selected files */
-
- rgba_char_args_set(btheme->tfile.image, 250, 250, 250, 255);
- rgba_char_args_set(btheme->tfile.movie, 250, 250, 250, 255);
- rgba_char_args_set(btheme->tfile.scene, 250, 250, 250, 255);
-
-
- /* space seq */
- btheme->tseq = btheme->tv3d;
- rgba_char_args_set(btheme->tseq.back, 116, 116, 116, 255);
- rgba_char_args_set(btheme->tseq.movie, 81, 105, 135, 255);
- rgba_char_args_set(btheme->tseq.movieclip, 32, 32, 143, 255);
- rgba_char_args_set(btheme->tseq.mask, 152, 78, 62, 255);
- rgba_char_args_set(btheme->tseq.image, 109, 88, 129, 255);
- rgba_char_args_set(btheme->tseq.scene, 78, 152, 62, 255);
- rgba_char_args_set(btheme->tseq.audio, 46, 143, 143, 255);
- rgba_char_args_set(btheme->tseq.effect, 169, 84, 124, 255);
- rgba_char_args_set(btheme->tseq.transition, 162, 95, 111, 255);
- rgba_char_args_set(btheme->tseq.meta, 109, 145, 131, 255);
- rgba_char_args_set(btheme->tseq.text_strip, 162, 151, 0, 255);
- rgba_char_args_set(btheme->tseq.preview_back, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tseq.grid, 64, 64, 64, 255);
-
- /* space image */
- btheme->tima = btheme->tv3d;
- rgba_char_args_set(btheme->tima.back, 53, 53, 53, 255);
- rgba_char_args_set(btheme->tima.vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tima.vertex_select, 255, 133, 0, 255);
- rgba_char_args_set(btheme->tima.wire_edit, 192, 192, 192, 255);
- rgba_char_args_set(btheme->tima.edge_select, 255, 133, 0, 255);
- btheme->tima.vertex_size = 3;
- btheme->tima.facedot_size = 3;
- rgba_char_args_set(btheme->tima.face, 255, 255, 255, 10);
- rgba_char_args_set(btheme->tima.face_select, 255, 133, 0, 60);
- rgba_char_args_set(btheme->tima.editmesh_active, 255, 255, 255, 128);
- rgba_char_args_set_fl(btheme->tima.preview_back, 0.0, 0.0, 0.0, 0.3);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_face, 0.5, 0.5, 0.0, 0.2);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_edge, 1.0, 0.0, 1.0, 0.2);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_vert, 0.0, 0.0, 1.0, 0.2);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_stitchable, 0.0, 1.0, 0.0, 1.0);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_unstitchable, 1.0, 0.0, 0.0, 1.0);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_active, 0.886, 0.824, 0.765, 0.140);
-
- rgba_char_args_test_set(btheme->tima.uv_others, 96, 96, 96, 255);
- rgba_char_args_test_set(btheme->tima.uv_shadow, 112, 112, 112, 255);
-
- ui_theme_space_init_handles_color(&btheme->tima);
- btheme->tima.handle_vertex_size = 5;
-
- /* space text */
- btheme->text = btheme->tv3d;
- rgba_char_args_set(btheme->text.back, 153, 153, 153, 255);
- rgba_char_args_set(btheme->text.shade1, 143, 143, 143, 255);
- rgba_char_args_set(btheme->text.shade2, 0xc6, 0x77, 0x77, 255);
- rgba_char_args_set(btheme->text.hilite, 255, 0, 0, 255);
-
- /* syntax highlighting */
- rgba_char_args_set(btheme->text.syntaxn, 0, 0, 200, 255); /* Numbers Blue*/
- rgba_char_args_set(btheme->text.syntaxl, 100, 0, 0, 255); /* Strings Red */
- rgba_char_args_set(btheme->text.syntaxc, 0, 100, 50, 255); /* Comments Greenish */
- rgba_char_args_set(btheme->text.syntaxv, 95, 95, 0, 255); /* Special Yellow*/
- rgba_char_args_set(btheme->text.syntaxd, 50, 0, 140, 255); /* Decorator/Preprocessor Dir. Blue-purple */
- rgba_char_args_set(btheme->text.syntaxr, 140, 60, 0, 255); /* Reserved Orange*/
- rgba_char_args_set(btheme->text.syntaxb, 128, 0, 80, 255); /* Builtin Red-purple */
- rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Gray (mix between fg/bg) */
-
- /* space oops */
- btheme->toops = btheme->tv3d;
- rgba_char_args_set_fl(btheme->toops.back, 0.45, 0.45, 0.45, 1.0);
-
- rgba_char_args_set_fl(btheme->toops.match, 0.2, 0.5, 0.2, 0.3); /* highlighting search match - soft green*/
- rgba_char_args_set_fl(btheme->toops.selected_highlight, 0.51, 0.53, 0.55, 0.3);
-
- /* space info */
- btheme->tinfo = btheme->tv3d;
- rgba_char_args_set_fl(btheme->tinfo.back, 0.45, 0.45, 0.45, 1.0);
- rgba_char_args_set(btheme->tinfo.info_selected, 96, 128, 255, 255);
- rgba_char_args_set(btheme->tinfo.info_selected_text, 255, 255, 255, 255);
- rgba_char_args_set(btheme->tinfo.info_error, 220, 0, 0, 255);
- rgba_char_args_set(btheme->tinfo.info_error_text, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tinfo.info_warning, 220, 128, 96, 255);
- rgba_char_args_set(btheme->tinfo.info_warning_text, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tinfo.info_info, 0, 170, 0, 255);
- rgba_char_args_set(btheme->tinfo.info_info_text, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tinfo.info_debug, 196, 196, 196, 255);
- rgba_char_args_set(btheme->tinfo.info_debug_text, 0, 0, 0, 255);
-
- /* space user preferences */
- btheme->tuserpref = btheme->tv3d;
- rgba_char_args_set_fl(btheme->tuserpref.back, 0.45, 0.45, 0.45, 1.0);
-
- /* space console */
- btheme->tconsole = btheme->tv3d;
- rgba_char_args_set(btheme->tconsole.back, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tconsole.console_output, 96, 128, 255, 255);
- rgba_char_args_set(btheme->tconsole.console_input, 255, 255, 255, 255);
- rgba_char_args_set(btheme->tconsole.console_info, 0, 170, 0, 255);
- rgba_char_args_set(btheme->tconsole.console_error, 220, 96, 96, 255);
- rgba_char_args_set(btheme->tconsole.console_cursor, 220, 96, 96, 255);
- rgba_char_args_set(btheme->tconsole.console_select, 255, 255, 255, 48);
-
- /* space time */
- btheme->ttime = btheme->tv3d;
- rgba_char_args_set_fl(btheme->ttime.back, 0.45, 0.45, 0.45, 1.0);
- rgba_char_args_set_fl(btheme->ttime.grid, 0.36, 0.36, 0.36, 1.0);
- rgba_char_args_set(btheme->ttime.shade1, 173, 173, 173, 255); /* sliders */
-
- rgba_char_args_set(btheme->ttime.time_keyframe, 0xDD, 0xD7, 0x00, 0xFF);
- rgba_char_args_set(btheme->ttime.time_gp_keyframe, 0xB5, 0xE6, 0x1D, 0xFF);
-
- /* space node, re-uses syntax and console color storage */
- btheme->tnode = btheme->tv3d;
- rgba_char_args_set(btheme->tnode.syntaxr, 115, 115, 115, 255); /* wire inner color */
- rgba_char_args_set(btheme->tnode.edge_select, 255, 255, 255, 255); /* wire selected */
- rgba_char_args_set(btheme->tnode.syntaxl, 155, 155, 155, 160); /* TH_NODE, backdrop */
- rgba_char_args_set(btheme->tnode.syntaxn, 100, 100, 100, 255); /* in */
- rgba_char_args_set(btheme->tnode.nodeclass_output, 100, 100, 100, 255); /* output */
- rgba_char_args_set(btheme->tnode.syntaxb, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.syntaxv, 104, 106, 117, 255); /* generator */
- rgba_char_args_set(btheme->tnode.syntaxc, 105, 117, 110, 255); /* group */
- rgba_char_args_set(btheme->tnode.nodeclass_texture, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.nodeclass_shader, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.nodeclass_filter, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.nodeclass_script, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.nodeclass_pattern, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.nodeclass_vector, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.nodeclass_layout, 108, 105, 111, 255); /* operator */
- rgba_char_args_set(btheme->tnode.movie, 155, 155, 155, 160); /* frame */
- rgba_char_args_set(btheme->tnode.syntaxs, 151, 116, 116, 255); /* matte nodes */
- rgba_char_args_set(btheme->tnode.syntaxd, 116, 151, 151, 255); /* distort nodes */
- rgba_char_args_set(btheme->tnode.console_output, 223, 202, 53, 255); /* interface nodes */
- btheme->tnode.noodle_curving = 5;
-
- /* space logic */
- btheme->tlogic = btheme->tv3d;
- rgba_char_args_set(btheme->tlogic.back, 100, 100, 100, 255);
-
- /* space clip */
- btheme->tclip = btheme->tv3d;
-
- rgba_char_args_set(btheme->tclip.marker_outline, 0x00, 0x00, 0x00, 255);
- rgba_char_args_set(btheme->tclip.marker, 0x7f, 0x7f, 0x00, 255);
- rgba_char_args_set(btheme->tclip.act_marker, 0xff, 0xff, 0xff, 255);
- rgba_char_args_set(btheme->tclip.sel_marker, 0xff, 0xff, 0x00, 255);
- rgba_char_args_set(btheme->tclip.dis_marker, 0x7f, 0x00, 0x00, 255);
- rgba_char_args_set(btheme->tclip.lock_marker, 0x7f, 0x7f, 0x7f, 255);
- rgba_char_args_set(btheme->tclip.path_before, 0xff, 0x00, 0x00, 255);
- rgba_char_args_set(btheme->tclip.path_after, 0x00, 0x00, 0xff, 255);
- rgba_char_args_set(btheme->tclip.grid, 0x5e, 0x5e, 0x5e, 255);
- rgba_char_args_set(btheme->tclip.cframe, 0x60, 0xc0, 0x40, 255);
- rgba_char_args_set(btheme->tclip.list, 0x66, 0x66, 0x66, 0xff);
- rgba_char_args_set(btheme->tclip.strip, 0x0c, 0x0a, 0x0a, 0x80);
- rgba_char_args_set(btheme->tclip.strip_select, 0xff, 0x8c, 0x00, 0xff);
- btheme->tclip.handle_vertex_size = 5;
- ui_theme_space_init_handles_color(&btheme->tclip);
+ const int active_theme_area = btheme->active_theme_area;
+ memcpy(btheme, &U_theme_default, sizeof(*btheme));
+ btheme->active_theme_area = active_theme_area;
}
void ui_style_init_default(void)
@@ -1273,25 +816,35 @@ void UI_ThemeColor4(int colorid)
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
glColor4ubv(cp);
-
}
/* set the color with offset for shades */
void UI_ThemeColorShade(int colorid, int offset)
{
- int r, g, b;
+ unsigned char col[4];
+ UI_GetThemeColorShade4ubv(colorid, offset, col);
+ glColor4ubv(col);
+}
+
+void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
+{
+ int r, g, b, a;
const unsigned char *cp;
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
- r = offset + (int) cp[0];
+ r = coloffset + (int) cp[0];
CLAMP(r, 0, 255);
- g = offset + (int) cp[1];
+ g = coloffset + (int) cp[1];
CLAMP(g, 0, 255);
- b = offset + (int) cp[2];
+ b = coloffset + (int) cp[2];
CLAMP(b, 0, 255);
- glColor4ub(r, g, b, cp[3]);
+ a = alphaoffset + (int) cp[3];
+ CLAMP(a, 0, 255);
+
+ glColor4ub(r, g, b, a);
}
-void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
+
+void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset, unsigned char col[4])
{
int r, g, b, a;
const unsigned char *cp;
@@ -1305,7 +858,11 @@ void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
CLAMP(b, 0, 255);
a = alphaoffset + (int) cp[3];
CLAMP(a, 0, 255);
- glColor4ub(r, g, b, a);
+
+ col[0] = r;
+ col[1] = g;
+ col[2] = b;
+ col[3] = a;
}
void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned char col[3])
@@ -1321,6 +878,19 @@ void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned c
col[2] = floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
}
+void UI_GetThemeColorBlend3f(int colorid1, int colorid2, float fac, float r_col[3])
+{
+ const unsigned char *cp1, *cp2;
+
+ cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+
+ CLAMP(fac, 0.0f, 1.0f);
+ r_col[0] = ((1.0f - fac) * cp1[0] + fac * cp2[0]) / 255.0f;
+ r_col[1] = ((1.0f - fac) * cp1[1] + fac * cp2[1]) / 255.0f;
+ r_col[2] = ((1.0f - fac) * cp1[2] + fac * cp2[2]) / 255.0f;
+}
+
/* blend between to theme colors, and set it */
void UI_ThemeColorBlend(int colorid1, int colorid2, float fac)
{
@@ -1373,6 +943,12 @@ void UI_ThemeColorBlendShadeAlpha(int colorid1, int colorid2, float fac, int off
glColor4ub(r, g, b, a);
}
+void UI_FontThemeColor(int fontid, int colorid)
+{
+ unsigned char color[4];
+ UI_GetThemeColor4ubv(colorid, color);
+ BLF_color4ubv(fontid, color);
+}
/* get individual values, not scaled */
float UI_GetThemeValuef(int colorid)
@@ -1471,6 +1047,111 @@ void UI_GetThemeColorShade3ubv(int colorid, int offset, unsigned char col[3])
col[2] = b;
}
+void UI_GetThemeColorBlendShade3ubv(int colorid1, int colorid2, float fac, int offset, unsigned char col[3])
+{
+ const unsigned char *cp1, *cp2;
+
+ cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+
+ CLAMP(fac, 0.0f, 1.0f);
+
+ float blend[3];
+ blend[0] = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
+ blend[1] = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
+ blend[2] = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
+
+ unit_float_to_uchar_clamp_v3(col, blend);
+}
+
+void UI_GetThemeColorShade4ubv(int colorid, int offset, unsigned char col[4])
+{
+ int r, g, b;
+ const unsigned char *cp;
+
+ cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ r = offset + (int) cp[0];
+ CLAMP(r, 0, 255);
+ g = offset + (int) cp[1];
+ CLAMP(g, 0, 255);
+ b = offset + (int) cp[2];
+ CLAMP(b, 0, 255);
+
+ col[0] = r;
+ col[1] = g;
+ col[2] = b;
+ col[3] = cp[3];
+}
+
+void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4])
+{
+ int r, g, b, a;
+ const unsigned char *cp;
+
+ cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+
+ r = coloffset + (int) cp[0];
+ CLAMP(r, 0, 255);
+ g = coloffset + (int) cp[1];
+ CLAMP(g, 0, 255);
+ b = coloffset + (int) cp[2];
+ CLAMP(b, 0, 255);
+ a = alphaoffset + (int) cp[3];
+ CLAMP(b, 0, 255);
+
+ col[0] = ((float)r) / 255.0f;
+ col[1] = ((float)g) / 255.0f;
+ col[2] = ((float)b) / 255.0f;
+ col[3] = ((float)a) / 255.0f;
+}
+
+void UI_GetThemeColorBlendShade3fv(int colorid1, int colorid2, float fac, int offset, float col[3])
+{
+ int r, g, b;
+ const unsigned char *cp1, *cp2;
+
+ cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+
+ CLAMP(fac, 0.0f, 1.0f);
+
+ r = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
+ CLAMP(r, 0, 255);
+ g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
+ CLAMP(g, 0, 255);
+ b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
+ CLAMP(b, 0, 255);
+
+ col[0] = ((float)r) / 255.0f;
+ col[1] = ((float)g) / 255.0f;
+ col[2] = ((float)b) / 255.0f;
+}
+
+void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4])
+{
+ int r, g, b, a;
+ const unsigned char *cp1, *cp2;
+
+ cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+
+ CLAMP(fac, 0.0f, 1.0f);
+
+ r = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
+ CLAMP(r, 0, 255);
+ g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
+ CLAMP(g, 0, 255);
+ b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
+ CLAMP(b, 0, 255);
+ a = offset + floorf((1.0f - fac) * cp1[3] + fac * cp2[3]);
+ CLAMP(a, 0, 255);
+
+ col[0] = ((float)r) / 255.0f;
+ col[1] = ((float)g) / 255.0f;
+ col[2] = ((float)b) / 255.0f;
+ col[3] = ((float)a) / 255.0f;
+}
+
/* get the color, in char pointer */
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3])
{
@@ -1588,14 +1269,14 @@ void UI_ThemeClearColor(int colorid)
float col[3];
UI_GetThemeColor3fv(colorid, col);
- glClearColor(col[0], col[1], col[2], 0.0f);
+ GPU_clear_color(col[0], col[1], col[2], 0.0f);
}
void UI_ThemeClearColorAlpha(int colorid, float alpha)
{
float col[3];
UI_GetThemeColor3fv(colorid, col);
- glClearColor(col[0], col[1], col[2], alpha);
+ GPU_clear_color(col[0], col[1], col[2], alpha);
}
@@ -1657,11 +1338,9 @@ void init_userdef_do_versions(Main *bmain)
U.savetime = 1;
// XXX error(STRINGIFY(BLENDER_STARTUP_FILE)" is buggy, please consider removing it.\n");
}
- /* transform widget settings */
- if (U.tw_hotspot == 0) {
- U.tw_hotspot = 14;
- U.tw_size = 25; /* percentage of window size */
- U.tw_handlesize = 16; /* percentage of widget radius */
+ if (U.manipulator_size == 0) {
+ U.manipulator_size = 75;
+ U.manipulator_flag |= USER_MANIPULATOR_DRAW;
}
if (U.pad_rot_angle == 0.0f)
U.pad_rot_angle = 15.0f;
@@ -1671,9 +1350,9 @@ void init_userdef_do_versions(Main *bmain)
U.fcu_inactive_alpha = 0.25f;
}
- /* signal for derivedmesh to use colorband */
+ /* signal for evaluated mesh to use colorband */
/* run in case this was on and is now off in the user prefs [#28096] */
- vDM_ColorBand_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL, UI_GetTheme()->tv3d.vertex_unreferenced);
+ BKE_mesh_runtime_color_band_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL, UI_GetTheme()->tv3d.vertex_unreferenced);
if (!USER_VERSION_ATLEAST(192, 0)) {
strcpy(U.sounddir, "/");
@@ -1686,243 +1365,40 @@ void init_userdef_do_versions(Main *bmain)
/* added seam, normal color, undo */
if (!USER_VERSION_ATLEAST(235, 0)) {
- bTheme *btheme;
-
U.uiflag |= USER_GLOBALUNDO;
if (U.undosteps == 0) U.undosteps = 32;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* check for (alpha == 0) is safe, then color was never set */
- if (btheme->tv3d.edge_seam[3] == 0) {
- rgba_char_args_set(btheme->tv3d.edge_seam, 230, 150, 50, 255);
- }
- if (btheme->tv3d.normal[3] == 0) {
- rgba_char_args_set(btheme->tv3d.normal, 0x22, 0xDD, 0xDD, 255);
- }
- if (btheme->tv3d.vertex_normal[3] == 0) {
- rgba_char_args_set(btheme->tv3d.vertex_normal, 0x23, 0x61, 0xDD, 255);
- }
- if (btheme->tv3d.face_dot[3] == 0) {
- rgba_char_args_set(btheme->tv3d.face_dot, 255, 138, 48, 255);
- btheme->tv3d.facedot_size = 4;
- }
- }
}
if (!USER_VERSION_ATLEAST(236, 0)) {
/* illegal combo... */
if (U.flag & USER_LMOUSESELECT)
U.flag &= ~USER_TWOBUTTONMOUSE;
}
- if (!USER_VERSION_ATLEAST(237, 0)) {
- bTheme *btheme;
- /* new space type */
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* check for (alpha == 0) is safe, then color was never set */
- if (btheme->ttime.back[3] == 0) {
- /* copied from ui_theme_init_default */
- btheme->ttime = btheme->tv3d;
- rgba_char_args_set_fl(btheme->ttime.back, 0.45, 0.45, 0.45, 1.0);
- rgba_char_args_set_fl(btheme->ttime.grid, 0.36, 0.36, 0.36, 1.0);
- rgba_char_args_set(btheme->ttime.shade1, 173, 173, 173, 255); /* sliders */
- }
- if (btheme->text.syntaxn[3] == 0) {
- rgba_char_args_set(btheme->text.syntaxn, 0, 0, 200, 255); /* Numbers Blue*/
- rgba_char_args_set(btheme->text.syntaxl, 100, 0, 0, 255); /* Strings red */
- rgba_char_args_set(btheme->text.syntaxc, 0, 100, 50, 255); /* Comments greenish */
- rgba_char_args_set(btheme->text.syntaxv, 95, 95, 0, 255); /* Special */
- rgba_char_args_set(btheme->text.syntaxb, 128, 0, 80, 255); /* Builtin, red-purple */
- }
- }
- }
- if (!USER_VERSION_ATLEAST(238, 0)) {
- bTheme *btheme;
- /* bone colors */
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* check for alpha==0 is safe, then color was never set */
- if (btheme->tv3d.bone_solid[3] == 0) {
- rgba_char_args_set(btheme->tv3d.bone_solid, 200, 200, 200, 255);
- rgba_char_args_set(btheme->tv3d.bone_pose, 80, 200, 255, 80);
- }
- }
- }
- if (!USER_VERSION_ATLEAST(239, 0)) {
- bTheme *btheme;
- /* bone colors */
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* check for alpha==0 is safe, then color was never set */
- if (btheme->tnla.strip[3] == 0) {
- rgba_char_args_set(btheme->tnla.strip_select, 0xff, 0xff, 0xaa, 255);
- rgba_char_args_set(btheme->tnla.strip, 0xe4, 0x9c, 0xc6, 255);
- }
- }
- }
if (!USER_VERSION_ATLEAST(240, 0)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* Lamp theme, check for alpha==0 is safe, then color was never set */
- if (btheme->tv3d.lamp[3] == 0) {
- rgba_char_args_set(btheme->tv3d.lamp, 0, 0, 0, 40);
-/* TEMPORAL, remove me! (ton) */
- U.uiflag |= USER_PLAINMENUS;
- }
-
- }
+ U.uiflag |= USER_PLAINMENUS;
if (U.obcenter_dia == 0) U.obcenter_dia = 6;
}
if (!USER_VERSION_ATLEAST(242, 0)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* Node editor theme, check for alpha==0 is safe, then color was never set */
- if (btheme->tnode.syntaxn[3] == 0) {
- /* re-uses syntax color storage */
- btheme->tnode = btheme->tv3d;
- rgba_char_args_set(btheme->tnode.edge_select, 255, 255, 255, 255);
- rgba_char_args_set(btheme->tnode.syntaxl, 150, 150, 150, 255); /* TH_NODE, backdrop */
- rgba_char_args_set(btheme->tnode.syntaxn, 129, 131, 144, 255); /* in/output */
- rgba_char_args_set(btheme->tnode.syntaxb, 127, 127, 127, 255); /* operator */
- rgba_char_args_set(btheme->tnode.syntaxv, 142, 138, 145, 255); /* generator */
- rgba_char_args_set(btheme->tnode.syntaxc, 120, 145, 120, 255); /* group */
- }
- /* Group theme colors */
- if (btheme->tv3d.group[3] == 0) {
- rgba_char_args_set(btheme->tv3d.group, 0x0C, 0x30, 0x0C, 255);
- rgba_char_args_set(btheme->tv3d.group_active, 0x66, 0xFF, 0x66, 255);
- }
- /* Sequence editor theme*/
- if (btheme->tseq.movie[3] == 0) {
- rgba_char_args_set(btheme->tseq.movie, 81, 105, 135, 255);
- rgba_char_args_set(btheme->tseq.image, 109, 88, 129, 255);
- rgba_char_args_set(btheme->tseq.scene, 78, 152, 62, 255);
- rgba_char_args_set(btheme->tseq.audio, 46, 143, 143, 255);
- rgba_char_args_set(btheme->tseq.effect, 169, 84, 124, 255);
- rgba_char_args_set(btheme->tseq.transition, 162, 95, 111, 255);
- rgba_char_args_set(btheme->tseq.meta, 109, 145, 131, 255);
- }
- }
-
/* set defaults for 3D View rotating axis indicator */
/* since size can't be set to 0, this indicates it's not saved in startup.blend */
if (U.rvisize == 0) {
U.rvisize = 15;
U.rvibright = 8;
- U.uiflag |= USER_SHOW_ROTVIEWICON;
+ U.uiflag |= USER_SHOW_MANIPULATOR_AXIS;
}
}
- if (!USER_VERSION_ATLEAST(243, 0)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* long keyframe color */
- /* check for alpha==0 is safe, then color was never set */
- if (btheme->tact.strip[3] == 0) {
- rgba_char_args_set(btheme->tv3d.edge_sharp, 255, 32, 32, 255);
- rgba_char_args_set(btheme->tact.strip_select, 0xff, 0xff, 0xaa, 204);
- rgba_char_args_set(btheme->tact.strip, 0xe4, 0x9c, 0xc6, 204);
- }
-
- /* IPO-Editor - Vertex Size*/
- if (btheme->tipo.vertex_size == 0) {
- btheme->tipo.vertex_size = 3;
- }
- }
- }
if (!USER_VERSION_ATLEAST(244, 0)) {
/* set default number of recently-used files (if not set) */
if (U.recent_files == 0) U.recent_files = 10;
}
if (!USER_VERSION_ATLEAST(245, 3)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tv3d.editmesh_active, 255, 255, 255, 128);
- }
if (U.coba_weight.tot == 0)
BKE_colorband_init(&U.coba_weight, true);
}
if (!USER_VERSION_ATLEAST(245, 3)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* these should all use the same color */
- rgba_char_args_set(btheme->tv3d.cframe, 0x60, 0xc0, 0x40, 255);
- rgba_char_args_set(btheme->tipo.cframe, 0x60, 0xc0, 0x40, 255);
- rgba_char_args_set(btheme->tact.cframe, 0x60, 0xc0, 0x40, 255);
- rgba_char_args_set(btheme->tnla.cframe, 0x60, 0xc0, 0x40, 255);
- rgba_char_args_set(btheme->tseq.cframe, 0x60, 0xc0, 0x40, 255);
- //rgba_char_args_set(btheme->tsnd.cframe, 0x60, 0xc0, 0x40, 255); Not needed anymore
- rgba_char_args_set(btheme->ttime.cframe, 0x60, 0xc0, 0x40, 255);
- }
- }
- if (!USER_VERSION_ATLEAST(245, 3)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* action channel groups (recolor anyway) */
- rgba_char_args_set(btheme->tact.group, 0x39, 0x7d, 0x1b, 255);
- rgba_char_args_set(btheme->tact.group_active, 0x7d, 0xe9, 0x60, 255);
-
- /* bone custom-color sets */
- if (btheme->tarm[0].solid[3] == 0)
- ui_theme_init_boneColorSets(btheme);
- }
- }
- if (!USER_VERSION_ATLEAST(245, 3)) {
U.flag |= USER_ADD_VIEWALIGNED | USER_ADD_EDITMODE;
}
- if (!USER_VERSION_ATLEAST(245, 3)) {
- bTheme *btheme;
-
- /* adjust themes */
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- const char *col;
-
- /* IPO Editor: Handles/Vertices */
- col = btheme->tipo.vertex;
- rgba_char_args_set(btheme->tipo.handle_vertex, col[0], col[1], col[2], 255);
- col = btheme->tipo.vertex_select;
- rgba_char_args_set(btheme->tipo.handle_vertex_select, col[0], col[1], col[2], 255);
- btheme->tipo.handle_vertex_size = btheme->tipo.vertex_size;
-
- /* Sequence/Image Editor: colors for GPencil text */
- col = btheme->tv3d.bone_pose;
- rgba_char_args_set(btheme->tseq.bone_pose, col[0], col[1], col[2], 255);
- rgba_char_args_set(btheme->tima.bone_pose, col[0], col[1], col[2], 255);
- col = btheme->tv3d.vertex_select;
- rgba_char_args_set(btheme->tseq.vertex_select, col[0], col[1], col[2], 255);
- }
- }
if (!USER_VERSION_ATLEAST(250, 0)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* this was not properly initialized in 2.45 */
- if (btheme->tima.face_dot[3] == 0) {
- rgba_char_args_set(btheme->tima.editmesh_active, 255, 255, 255, 128);
- rgba_char_args_set(btheme->tima.face_dot, 255, 133, 0, 255);
- btheme->tima.facedot_size = 2;
- }
-
- /* DopeSheet - (Object) Channel color */
- rgba_char_args_set(btheme->tact.ds_channel, 82, 96, 110, 255);
- rgba_char_args_set(btheme->tact.ds_subchannel, 124, 137, 150, 255);
- /* DopeSheet - Group Channel color (saner version) */
- rgba_char_args_set(btheme->tact.group, 79, 101, 73, 255);
- rgba_char_args_set(btheme->tact.group_active, 135, 177, 125, 255);
-
- /* Graph Editor - (Object) Channel color */
- rgba_char_args_set(btheme->tipo.ds_channel, 82, 96, 110, 255);
- rgba_char_args_set(btheme->tipo.ds_subchannel, 124, 137, 150, 255);
- /* Graph Editor - Group Channel color */
- rgba_char_args_set(btheme->tipo.group, 79, 101, 73, 255);
- rgba_char_args_set(btheme->tipo.group_active, 135, 177, 125, 255);
-
- /* Nla Editor - (Object) Channel color */
- rgba_char_args_set(btheme->tnla.ds_channel, 82, 96, 110, 255);
- rgba_char_args_set(btheme->tnla.ds_subchannel, 124, 137, 150, 255);
- /* NLA Editor - New Strip colors */
- rgba_char_args_set(btheme->tnla.strip, 12, 10, 10, 128);
- rgba_char_args_set(btheme->tnla.strip_select, 255, 140, 0, 255);
- }
-
/* adjust grease-pencil distances */
U.gp_manhattendist = 1;
U.gp_euclideandist = 2;
@@ -1931,29 +1407,6 @@ void init_userdef_do_versions(Main *bmain)
U.ipo_new = BEZT_IPO_BEZ;
}
- if (!USER_VERSION_ATLEAST(250, 1)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
-
- /* common (new) variables, it checks for alpha==0 */
- ui_theme_init_new(btheme);
-
- if (btheme->tui.wcol_num.outline[3] == 0)
- ui_widget_color_init(&btheme->tui);
-
- /* Logic editor theme, check for alpha==0 is safe, then color was never set */
- if (btheme->tlogic.syntaxn[3] == 0) {
- /* re-uses syntax color storage */
- btheme->tlogic = btheme->tv3d;
- rgba_char_args_set(btheme->tlogic.back, 100, 100, 100, 255);
- }
-
- rgba_char_args_set_fl(btheme->tinfo.back, 0.45, 0.45, 0.45, 1.0);
- rgba_char_args_set_fl(btheme->tuserpref.back, 0.45, 0.45, 0.45, 1.0);
- }
- }
-
if (!USER_VERSION_ATLEAST(250, 3)) {
/* new audio system */
if (U.audiochannels == 0)
@@ -1984,8 +1437,6 @@ void init_userdef_do_versions(Main *bmain)
strcpy(km->idname, "3D View Generic");
else if (STREQ(km->idname, "EditMesh"))
strcpy(km->idname, "Mesh");
- else if (STREQ(km->idname, "TimeLine"))
- strcpy(km->idname, "Timeline");
else if (STREQ(km->idname, "UVEdit"))
strcpy(km->idname, "UV Editor");
else if (STREQ(km->idname, "Animation_Channels"))
@@ -2012,76 +1463,14 @@ void init_userdef_do_versions(Main *bmain)
strcpy(km->idname, "Property Editor");
}
}
- if (!USER_VERSION_ATLEAST(250, 16)) {
- if (U.wmdrawmethod == USER_DRAW_TRIPLE)
- U.wmdrawmethod = USER_DRAW_AUTOMATIC;
- }
if (!USER_VERSION_ATLEAST(252, 3)) {
if (U.flag & USER_LMOUSESELECT)
U.flag &= ~USER_TWOBUTTONMOUSE;
}
if (!USER_VERSION_ATLEAST(252, 4)) {
- bTheme *btheme;
-
/* default new handle type is auto handles */
U.keyhandles_new = HD_AUTO;
-
- /* init new curve colors */
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- ui_theme_space_init_handles_color(&btheme->tv3d);
- ui_theme_space_init_handles_color(&btheme->tipo);
-
- /* edge crease */
- rgba_char_args_set_fl(btheme->tv3d.edge_crease, 0.8, 0, 0.6, 1.0);
- }
- }
- if (!USER_VERSION_ATLEAST(253, 0)) {
- bTheme *btheme;
-
- /* init new curve colors */
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tv3d.lastsel_point[3] == 0)
- rgba_char_args_set(btheme->tv3d.lastsel_point, 0xff, 0xff, 0xff, 255);
- }
- }
- if (!USER_VERSION_ATLEAST(252, 5)) {
- bTheme *btheme;
-
- /* interface_widgets.c */
- struct uiWidgetColors wcol_progress = {
- {0, 0, 0, 255},
- {190, 190, 190, 255},
- {100, 100, 100, 180},
- {128, 128, 128, 255},
-
- {0, 0, 0, 255},
- {255, 255, 255, 255},
-
- 0,
- 5, -5
- };
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* init progress bar theme */
- btheme->tui.wcol_progress = wcol_progress;
- }
- }
-
- if (!USER_VERSION_ATLEAST(255, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tv3d.extra_edge_len, 32, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.extra_face_angle, 0, 32, 0, 255);
- rgba_char_args_set(btheme->tv3d.extra_face_area, 0, 0, 128, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(256, 4)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if ((btheme->tv3d.outline_width) == 0) btheme->tv3d.outline_width = 1;
- }
}
if (!USER_VERSION_ATLEAST(257, 0)) {
@@ -2090,226 +1479,22 @@ void init_userdef_do_versions(Main *bmain)
U.autokey_flag &= ~AUTOKEY_FLAG_ONLYKEYINGSET;
}
- if (!USER_VERSION_ATLEAST(258, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- btheme->tnode.noodle_curving = 5;
- }
- }
-
- if (!USER_VERSION_ATLEAST(259, 1)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- btheme->tv3d.speaker[3] = 255;
- }
- }
-
if (!USER_VERSION_ATLEAST(260, 3)) {
- bTheme *btheme;
-
/* if new keyframes handle default is stuff "auto", make it "auto-clamped" instead
* was changed in 260 as part of GSoC11, but version patch was wrong
*/
if (U.keyhandles_new == HD_AUTO)
U.keyhandles_new = HD_AUTO_ANIM;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tv3d.bundle_solid[3] == 0)
- rgba_char_args_set(btheme->tv3d.bundle_solid, 200, 200, 200, 255);
-
- if (btheme->tv3d.camera_path[3] == 0)
- rgba_char_args_set(btheme->tv3d.camera_path, 0x00, 0x00, 0x00, 255);
-
- if ((btheme->tclip.back[3]) == 0) {
- btheme->tclip = btheme->tv3d;
-
- rgba_char_args_set(btheme->tclip.marker_outline, 0x00, 0x00, 0x00, 255);
- rgba_char_args_set(btheme->tclip.marker, 0x7f, 0x7f, 0x00, 255);
- rgba_char_args_set(btheme->tclip.act_marker, 0xff, 0xff, 0xff, 255);
- rgba_char_args_set(btheme->tclip.sel_marker, 0xff, 0xff, 0x00, 255);
- rgba_char_args_set(btheme->tclip.dis_marker, 0x7f, 0x00, 0x00, 255);
- rgba_char_args_set(btheme->tclip.lock_marker, 0x7f, 0x7f, 0x7f, 255);
- rgba_char_args_set(btheme->tclip.path_before, 0xff, 0x00, 0x00, 255);
- rgba_char_args_set(btheme->tclip.path_after, 0x00, 0x00, 0xff, 255);
- rgba_char_args_set(btheme->tclip.grid, 0x5e, 0x5e, 0x5e, 255);
- rgba_char_args_set(btheme->tclip.cframe, 0x60, 0xc0, 0x40, 255);
- rgba_char_args_set(btheme->tclip.handle_vertex, 0x00, 0x00, 0x00, 0xff);
- rgba_char_args_set(btheme->tclip.handle_vertex_select, 0xff, 0xff, 0, 0xff);
- btheme->tclip.handle_vertex_size = 5;
- }
-
- /* auto-clamped handles -> based on auto */
- if (btheme->tipo.handle_auto_clamped[3] == 0)
- rgba_char_args_set(btheme->tipo.handle_auto_clamped, 0x99, 0x40, 0x30, 255);
- if (btheme->tipo.handle_sel_auto_clamped[3] == 0)
- rgba_char_args_set(btheme->tipo.handle_sel_auto_clamped, 0xf0, 0xaf, 0x90, 255);
- }
-
/* enable (Cycles) addon by default */
BKE_addon_ensure(&U.addons, "cycles");
}
- if (!USER_VERSION_ATLEAST(260, 5)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tui.panel.header, 0, 0, 0, 25);
- btheme->tui.icon_alpha = 1.0;
- }
- }
-
if (!USER_VERSION_ATLEAST(261, 4)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set_fl(btheme->tima.preview_stitch_face, 0.071, 0.259, 0.694, 0.150);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_edge, 1.0, 0.522, 0.0, 0.7);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_vert, 1.0, 0.522, 0.0, 0.5);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_stitchable, 0.0, 1.0, 0.0, 1.0);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_unstitchable, 1.0, 0.0, 0.0, 1.0);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_active, 0.886, 0.824, 0.765, 0.140);
-
- rgba_char_args_set_fl(btheme->toops.match, 0.2, 0.5, 0.2, 0.3);
- rgba_char_args_set_fl(btheme->toops.selected_highlight, 0.51, 0.53, 0.55, 0.3);
- }
-
U.use_16bit_textures = true;
}
- if (!USER_VERSION_ATLEAST(262, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tui.wcol_menu_item.item[3] == 255)
- rgba_char_args_set(btheme->tui.wcol_menu_item.item, 172, 172, 172, 128);
- }
- }
-
- if (!USER_VERSION_ATLEAST(262, 3)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tui.wcol_tooltip.inner[3] == 0) {
- btheme->tui.wcol_tooltip = btheme->tui.wcol_menu_back;
- }
- if (btheme->tui.wcol_tooltip.text[0] == 160) { /* hrmf */
- rgba_char_args_set(btheme->tui.wcol_tooltip.text, 255, 255, 255, 255);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(262, 4)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tseq.movieclip[3] == 0) {
- rgba_char_args_set(btheme->tseq.movieclip, 32, 32, 143, 255);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(263, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tclip.strip[0] == 0) {
- rgba_char_args_set(btheme->tclip.list, 0x66, 0x66, 0x66, 0xff);
- rgba_char_args_set(btheme->tclip.strip, 0x0c, 0x0a, 0x0a, 0x80);
- rgba_char_args_set(btheme->tclip.strip_select, 0xff, 0x8c, 0x00, 0xff);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(263, 6)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next)
- rgba_char_args_set(btheme->tv3d.skin_root, 180, 77, 77, 255);
- }
-
- if (!USER_VERSION_ATLEAST(263, 7)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* DopeSheet Summary */
- rgba_char_args_set(btheme->tact.anim_active, 204, 112, 26, 102);
-
- /* NLA Colors */
- rgba_char_args_set(btheme->tnla.anim_active, 204, 112, 26, 102); /* same as dopesheet above */
- rgba_char_args_set(btheme->tnla.anim_non_active, 153, 135, 97, 77);
-
- rgba_char_args_set(btheme->tnla.nla_tweaking, 77, 243, 26, 77);
- rgba_char_args_set(btheme->tnla.nla_tweakdupli, 217, 0, 0, 255);
-
- rgba_char_args_set(btheme->tnla.nla_transition, 28, 38, 48, 255);
- rgba_char_args_set(btheme->tnla.nla_transition_sel, 46, 117, 219, 255);
- rgba_char_args_set(btheme->tnla.nla_meta, 51, 38, 66, 255);
- rgba_char_args_set(btheme->tnla.nla_meta_sel, 105, 33, 150, 255);
- rgba_char_args_set(btheme->tnla.nla_sound, 43, 61, 61, 255);
- rgba_char_args_set(btheme->tnla.nla_sound_sel, 31, 122, 122, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(263, 11)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tseq.mask[3] == 0) {
- rgba_char_args_set(btheme->tseq.mask, 152, 78, 62, 255);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(263, 15)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tv3d.bone_pose_active, 140, 255, 255, 80);
- }
- }
-
- if (!USER_VERSION_ATLEAST(263, 16)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tact.anim_active[3] == 0)
- rgba_char_args_set(btheme->tact.anim_active, 204, 112, 26, 102);
-
- if (btheme->tnla.anim_active[3] == 0)
- rgba_char_args_set(btheme->tnla.anim_active, 204, 112, 26, 102);
- }
- }
-
- if (!USER_VERSION_ATLEAST(263, 22)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tipo.lastsel_point[3] == 0)
- rgba_char_args_set(btheme->tipo.lastsel_point, 0xff, 0xff, 0xff, 255);
-
- if (btheme->tv3d.skin_root[3] == 0)
- rgba_char_args_set(btheme->tv3d.skin_root, 180, 77, 77, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(264, 9)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tui.xaxis, 220, 0, 0, 255);
- rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255);
- rgba_char_args_set(btheme->tui.zaxis, 0, 0, 220, 255);
- }
- }
-
if (!USER_VERSION_ATLEAST(267, 0)) {
- /* Freestyle color settings */
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* check for alpha == 0 is safe, then color was never set */
- if (btheme->tv3d.freestyle_edge_mark[3] == 0) {
- rgba_char_args_set(btheme->tv3d.freestyle_edge_mark, 0x7f, 0xff, 0x7f, 255);
- rgba_char_args_set(btheme->tv3d.freestyle_face_mark, 0x7f, 0xff, 0x7f, 51);
- }
-
- if (btheme->tv3d.wire_edit[3] == 0) {
- rgba_char_args_set(btheme->tv3d.wire_edit, 0x0, 0x0, 0x0, 255);
- }
- }
/* GL Texture Garbage Collection */
if (U.textimeout == 0) {
@@ -2319,9 +1504,6 @@ void init_userdef_do_versions(Main *bmain)
if (U.memcachelimit <= 0) {
U.memcachelimit = 32;
}
- if (U.frameserverport == 0) {
- U.frameserverport = 8080;
- }
if (U.dbl_click_time == 0) {
U.dbl_click_time = 350;
}
@@ -2350,178 +1532,12 @@ void init_userdef_do_versions(Main *bmain)
U.tweak_threshold = 10;
}
- if (!USER_VERSION_ATLEAST(265, 1)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* note: the toggle operator for transparent backdrops limits to these spacetypes */
- if (btheme->tnode.button[3] == 255) {
- btheme->tv3d.button[3] = 128;
- btheme->tnode.button[3] = 128;
- btheme->tima.button[3] = 128;
- btheme->tseq.button[3] = 128;
- btheme->tclip.button[3] = 128;
- }
- }
- }
-
- /* panel header/backdrop supported locally per editor now */
- if (!USER_VERSION_ATLEAST(265, 2)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- ThemeSpace *ts;
-
- /* new color, panel backdrop. Not used anywhere yet, until you enable it */
- copy_v3_v3_char(btheme->tui.panel.back, btheme->tbuts.button);
- btheme->tui.panel.back[3] = 128;
-
- for (ts = UI_THEMESPACE_START(btheme); ts != UI_THEMESPACE_END(btheme); ts++) {
- ts->panelcolors = btheme->tui.panel;
- }
- }
- }
-
/* NOTE!! from now on use U.versionfile and U.subversionfile */
#undef USER_VERSION_ATLEAST
#define USER_VERSION_ATLEAST(ver, subver) MAIN_VERSION_ATLEAST((&(U)), ver, subver)
- if (!USER_VERSION_ATLEAST(266, 0)) {
- bTheme *btheme;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* rna definition limits fac to 0.01 */
- if (btheme->tui.menu_shadow_fac == 0.0f) {
- btheme->tui.menu_shadow_fac = 0.5f;
- btheme->tui.menu_shadow_width = 12;
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(265, 4)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->text.syntaxd, 50, 0, 140, 255); /* Decorator/Preprocessor Dir. Blue-purple */
- rgba_char_args_set(btheme->text.syntaxr, 140, 60, 0, 255); /* Reserved Orange */
- rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Gray (mix between fg/bg) */
- }
- }
-
- if (!USER_VERSION_ATLEAST(265, 6)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- copy_v4_v4_char(btheme->tv3d.gradients.high_gradient, btheme->tv3d.back);
- }
- }
-
- if (!USER_VERSION_ATLEAST(265, 9)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_test_set(btheme->tnode.syntaxs, 151, 116, 116, 255); /* matte nodes */
- rgba_char_args_test_set(btheme->tnode.syntaxd, 116, 151, 151, 255); /* distort nodes */
- }
- }
-
- if (!USER_VERSION_ATLEAST(265, 11)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_test_set(btheme->tconsole.console_select, 255, 255, 255, 48);
- }
- }
-
- if (!USER_VERSION_ATLEAST(266, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_test_set(btheme->tnode.console_output, 223, 202, 53, 255); /* interface nodes */
- }
- }
-
- if (!USER_VERSION_ATLEAST(268, 3)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_test_set(btheme->tima.uv_others, 96, 96, 96, 255);
- rgba_char_args_test_set(btheme->tima.uv_shadow, 112, 112, 112, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(269, 5)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tima.wire_edit, 192, 192, 192, 255);
- rgba_char_args_set(btheme->tima.edge_select, 255, 133, 0, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(269, 6)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- char r, g, b;
- r = btheme->tnode.syntaxn[0];
- g = btheme->tnode.syntaxn[1];
- b = btheme->tnode.syntaxn[2];
- rgba_char_args_test_set(btheme->tnode.nodeclass_output, r, g, b, 255);
- r = btheme->tnode.syntaxb[0];
- g = btheme->tnode.syntaxb[1];
- b = btheme->tnode.syntaxb[2];
- rgba_char_args_test_set(btheme->tnode.nodeclass_filter, r, g, b, 255);
- rgba_char_args_test_set(btheme->tnode.nodeclass_vector, r, g, b, 255);
- rgba_char_args_test_set(btheme->tnode.nodeclass_texture, r, g, b, 255);
- rgba_char_args_test_set(btheme->tnode.nodeclass_shader, r, g, b, 255);
- rgba_char_args_test_set(btheme->tnode.nodeclass_script, r, g, b, 255);
- rgba_char_args_test_set(btheme->tnode.nodeclass_pattern, r, g, b, 255);
- rgba_char_args_test_set(btheme->tnode.nodeclass_layout, r, g, b, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(269, 8)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_test_set(btheme->tinfo.info_selected, 96, 128, 255, 255);
- rgba_char_args_test_set(btheme->tinfo.info_selected_text, 255, 255, 255, 255);
- rgba_char_args_test_set(btheme->tinfo.info_error, 220, 0, 0, 255);
- rgba_char_args_test_set(btheme->tinfo.info_error_text, 0, 0, 0, 255);
- rgba_char_args_test_set(btheme->tinfo.info_warning, 220, 128, 96, 255);
- rgba_char_args_test_set(btheme->tinfo.info_warning_text, 0, 0, 0, 255);
- rgba_char_args_test_set(btheme->tinfo.info_info, 0, 170, 0, 255);
- rgba_char_args_test_set(btheme->tinfo.info_info_text, 0, 0, 0, 255);
- rgba_char_args_test_set(btheme->tinfo.info_debug, 196, 196, 196, 255);
- rgba_char_args_test_set(btheme->tinfo.info_debug_text, 0, 0, 0, 255);
- }
- }
if (!USER_VERSION_ATLEAST(269, 9)) {
- bTheme *btheme;
-
- U.tw_size = U.tw_size * 5.0f;
-
- /* Action Editor (and NLA Editor) - Keyframe Colors */
- /* Graph Editor - larger vertex size defaults */
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* Action Editor ................. */
- /* key types */
- rgba_char_args_set(btheme->tact.keytype_keyframe, 232, 232, 232, 255);
- rgba_char_args_set(btheme->tact.keytype_keyframe_select, 255, 190, 50, 255);
- rgba_char_args_set(btheme->tact.keytype_extreme, 232, 179, 204, 255);
- rgba_char_args_set(btheme->tact.keytype_extreme_select, 242, 128, 128, 255);
- rgba_char_args_set(btheme->tact.keytype_breakdown, 179, 219, 232, 255);
- rgba_char_args_set(btheme->tact.keytype_breakdown_select, 84, 191, 237, 255);
- rgba_char_args_set(btheme->tact.keytype_jitter, 148, 229, 117, 255);
- rgba_char_args_set(btheme->tact.keytype_jitter_select, 97, 192, 66, 255);
-
- /* key border */
- rgba_char_args_set(btheme->tact.keyborder, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tact.keyborder_select, 0, 0, 0, 255);
-
- /* NLA ............................ */
- /* key border */
- rgba_char_args_set(btheme->tnla.keyborder, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tnla.keyborder_select, 0, 0, 0, 255);
-
- /* Graph Editor ................... */
- btheme->tipo.vertex_size = 6;
- btheme->tipo.handle_vertex_size = 5;
- }
-
/* grease pencil - new layer color */
if (U.gpencil_new_layer_col[3] < 0.1f) {
/* defaults to black, but must at least be visible! */
@@ -2529,143 +1545,10 @@ void init_userdef_do_versions(Main *bmain)
}
}
- if (!USER_VERSION_ATLEAST(269, 10)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- ThemeSpace *ts;
-
- for (ts = UI_THEMESPACE_START(btheme); ts != UI_THEMESPACE_END(btheme); ts++) {
- rgba_char_args_set(ts->tab_active, 114, 114, 114, 255);
- rgba_char_args_set(ts->tab_inactive, 83, 83, 83, 255);
- rgba_char_args_set(ts->tab_back, 64, 64, 64, 255);
- rgba_char_args_set(ts->tab_outline, 60, 60, 60, 255);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(271, 0)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tui.wcol_tooltip.text, 255, 255, 255, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(272, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set_fl(btheme->tv3d.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
- rgba_char_args_set_fl(btheme->tv3d.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
- rgba_char_args_set_fl(btheme->tima.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
- rgba_char_args_set_fl(btheme->tima.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
- rgba_char_args_set(btheme->tnode.syntaxr, 115, 115, 115, 255);
- }
- }
-
if (!USER_VERSION_ATLEAST(271, 5)) {
- bTheme *btheme;
-
- struct uiWidgetColors wcol_pie_menu = {
- {10, 10, 10, 200},
- {25, 25, 25, 230},
- {140, 140, 140, 255},
- {45, 45, 45, 230},
-
- {160, 160, 160, 255},
- {255, 255, 255, 255},
-
- 1,
- 10, -10
- };
-
U.pie_menu_radius = 100;
U.pie_menu_threshold = 12;
U.pie_animation_timeout = 6;
-
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- btheme->tui.wcol_pie_menu = wcol_pie_menu;
-
- ui_theme_space_init_handles_color(&btheme->tclip);
- ui_theme_space_init_handles_color(&btheme->tima);
- btheme->tima.handle_vertex_size = 5;
- btheme->tclip.handle_vertex_size = 5;
- }
- }
-
- if (!USER_VERSION_ATLEAST(271, 6)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* check for (alpha == 0) is safe, then color was never set */
- if (btheme->tv3d.loop_normal[3] == 0) {
- rgba_char_args_set(btheme->tv3d.loop_normal, 0xDD, 0x23, 0xDD, 255);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(272, 3)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set_fl(btheme->tui.widget_emboss, 1.0f, 1.0f, 1.0f, 0.02f);
- }
- }
-
- if (!USER_VERSION_ATLEAST(273, 1)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* Grease Pencil vertex settings */
- rgba_char_args_set(btheme->tv3d.gp_vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.gp_vertex_select, 255, 133, 0, 255);
- btheme->tv3d.gp_vertex_size = 3;
-
- rgba_char_args_set(btheme->tseq.gp_vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tseq.gp_vertex_select, 255, 133, 0, 255);
- btheme->tseq.gp_vertex_size = 3;
-
- rgba_char_args_set(btheme->tima.gp_vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tima.gp_vertex_select, 255, 133, 0, 255);
- btheme->tima.gp_vertex_size = 3;
-
- rgba_char_args_set(btheme->tnode.gp_vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tnode.gp_vertex_select, 255, 133, 0, 255);
- btheme->tnode.gp_vertex_size = 3;
-
- /* Timeline Keyframe Indicators */
- rgba_char_args_set(btheme->ttime.time_keyframe, 0xDD, 0xD7, 0x00, 0xFF);
- rgba_char_args_set(btheme->ttime.time_gp_keyframe, 0xB5, 0xE6, 0x1D, 0xFF);
- }
- }
-
- if (!USER_VERSION_ATLEAST(273, 5)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- unsigned char *cp = (unsigned char *)btheme->tv3d.clipping_border_3d;
- int c;
- copy_v4_v4_char((char *)cp, btheme->tv3d.back);
- c = cp[0] - 8;
- CLAMP(c, 0, 255);
- cp[0] = c;
- c = cp[1] - 8;
- CLAMP(c, 0, 255);
- cp[1] = c;
- c = cp[2] - 8;
- CLAMP(c, 0, 255);
- cp[2] = c;
- cp[3] = 255;
- }
- }
-
- if (!USER_VERSION_ATLEAST(274, 5)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- copy_v4_v4_char(btheme->tima.metadatatext, btheme->tima.text_hi);
- copy_v4_v4_char(btheme->tseq.metadatatext, btheme->tseq.text_hi);
- }
- }
-
- if (!USER_VERSION_ATLEAST(275, 1)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- copy_v4_v4_char(btheme->tclip.metadatatext, btheme->tseq.text_hi);
- }
}
if (!USER_VERSION_ATLEAST(275, 2)) {
@@ -2676,83 +1559,10 @@ void init_userdef_do_versions(Main *bmain)
U.node_margin = 80;
}
- if (!USER_VERSION_ATLEAST(276, 1)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set_fl(btheme->tima.preview_back, 0.0f, 0.0f, 0.0f, 0.3f);
- }
- }
-
- if (!USER_VERSION_ATLEAST(276, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tclip.gp_vertex, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tclip.gp_vertex_select, 255, 133, 0, 255);
- btheme->tclip.gp_vertex_size = 3;
- }
- }
-
- if (!USER_VERSION_ATLEAST(276, 3)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tseq.text_strip, 162, 151, 0, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(276, 8)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tui.wcol_progress.item, 128, 128, 128, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(276, 10)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* 3dView Keyframe Indicators */
- rgba_char_args_set(btheme->tv3d.time_keyframe, 0xDD, 0xD7, 0x00, 0xFF);
- rgba_char_args_set(btheme->tv3d.time_gp_keyframe, 0xB5, 0xE6, 0x1D, 0xFF);
- }
- }
-
- if (!USER_VERSION_ATLEAST(277, 0)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (memcmp(btheme->tui.wcol_list_item.item, btheme->tui.wcol_list_item.text_sel, sizeof(char) * 3) == 0) {
- copy_v4_v4_char(btheme->tui.wcol_list_item.item, btheme->tui.wcol_text.item);
- copy_v4_v4_char(btheme->tui.wcol_list_item.text_sel, btheme->tui.wcol_text.text_sel);
- }
- }
- }
-
- if (!USER_VERSION_ATLEAST(277, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- if (btheme->tact.keyframe_scale_fac < 0.1f)
- btheme->tact.keyframe_scale_fac = 1.0f;
- }
- }
-
- if (!USER_VERSION_ATLEAST(278, 2)) {
- bTheme *btheme;
- for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- rgba_char_args_set(btheme->tv3d.vertex_bevel, 0, 165, 255, 255);
- rgba_char_args_set(btheme->tv3d.edge_bevel, 0, 165, 255, 255);
- }
- }
-
- if (!USER_VERSION_ATLEAST(278, 3)) {
- for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* Keyframe Indicators (were using wrong alpha) */
- btheme->tv3d.time_keyframe[3] = btheme->tv3d.time_gp_keyframe[3] = 255;
- btheme->ttime.time_keyframe[3] = btheme->ttime.time_gp_keyframe[3] = 255;
- }
- }
-
if (!USER_VERSION_ATLEAST(278, 6)) {
/* Clear preference flags for re-use. */
U.flag &= ~(
- USER_FLAG_DEPRECATED_1 | USER_FLAG_DEPRECATED_2 | USER_FLAG_DEPRECATED_3 |
+ USER_FLAG_NUMINPUT_ADVANCED | USER_FLAG_DEPRECATED_2 | USER_FLAG_DEPRECATED_3 |
USER_FLAG_DEPRECATED_6 | USER_FLAG_DEPRECATED_7 |
USER_FLAG_DEPRECATED_9 | USER_DEVELOPER_UI);
U.uiflag &= ~(
@@ -2760,13 +1570,20 @@ void init_userdef_do_versions(Main *bmain)
U.transopts &= ~(
USER_TR_DEPRECATED_2 | USER_TR_DEPRECATED_3 | USER_TR_DEPRECATED_4 |
USER_TR_DEPRECATED_6 | USER_TR_DEPRECATED_7);
- U.gameflags &= ~(
- USER_GL_RENDER_DEPRECATED_0 | USER_GL_RENDER_DEPRECATED_1 |
- USER_GL_RENDER_DEPRECATED_3 | USER_GL_RENDER_DEPRECATED_4);
U.uiflag |= USER_LOCK_CURSOR_ADJUST;
}
+
+ if (!USER_VERSION_ATLEAST(280, 20)) {
+ U.gpu_viewport_quality = 0.6f;
+
+ /* Reset theme, old themes will not be compatible with minor version updates from now on. */
+ for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
+ memcpy(btheme, &U_theme_default, sizeof(*btheme));
+ }
+ }
+
/**
* Include next version bump.
*/
@@ -2780,11 +1597,8 @@ void init_userdef_do_versions(Main *bmain)
if (U.image_draw_method == 0)
U.image_draw_method = IMAGE_DRAW_METHOD_2DTEXTURE;
- // keep the following until the new audaspace is default to be built with
-#ifdef WITH_SYSTEM_AUDASPACE
// we default to the first audio device
U.audiodevice = 0;
-#endif
/* Not versioning, just avoid errors. */
#ifndef WITH_CYCLES
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 299001d4e45..1b449877abe 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -49,11 +49,12 @@
#include "BKE_screen.h"
#include "BKE_global.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "WM_api.h"
-#include "BIF_gl.h"
-
#include "BLF_api.h"
#include "ED_screen.h"
@@ -147,50 +148,50 @@ static void view2d_masks(View2D *v2d, bool check_scrollers)
scroll = view2d_scroll_mapped(v2d->scroll);
- /* scrollers shrink mask area, but should be based off regionsize
+ /* scrollers are based off regionsize
* - they can only be on one to two edges of the region they define
* - if they overlap, they must not occupy the corners (which are reserved for other widgets)
*/
if (scroll) {
+ const int scroll_width = (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) ?
+ V2D_SCROLL_WIDTH_TEXT : V2D_SCROLL_WIDTH;
+ const int scroll_height = (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) ?
+ V2D_SCROLL_HEIGHT_TEXT : V2D_SCROLL_HEIGHT;
+
/* vertical scroller */
if (scroll & V2D_SCROLL_LEFT) {
/* on left-hand edge of region */
v2d->vert = v2d->mask;
- v2d->vert.xmax = V2D_SCROLL_WIDTH;
- v2d->mask.xmin = v2d->vert.xmax + 1;
+ v2d->vert.xmax = scroll_width;
}
else if (scroll & V2D_SCROLL_RIGHT) {
/* on right-hand edge of region */
v2d->vert = v2d->mask;
v2d->vert.xmax++; /* one pixel extra... was leaving a minor gap... */
- v2d->vert.xmin = v2d->vert.xmax - V2D_SCROLL_WIDTH;
- v2d->mask.xmax = v2d->vert.xmin - 1;
+ v2d->vert.xmin = v2d->vert.xmax - scroll_width;
}
/* horizontal scroller */
if (scroll & (V2D_SCROLL_BOTTOM)) {
/* on bottom edge of region */
v2d->hor = v2d->mask;
- v2d->hor.ymax = V2D_SCROLL_HEIGHT;
- v2d->mask.ymin = v2d->hor.ymax + 1;
+ v2d->hor.ymax = scroll_height;
}
else if (scroll & V2D_SCROLL_TOP) {
/* on upper edge of region */
v2d->hor = v2d->mask;
- v2d->hor.ymin = v2d->hor.ymax - V2D_SCROLL_HEIGHT;
- v2d->mask.ymax = v2d->hor.ymin - 1;
+ v2d->hor.ymin = v2d->hor.ymax - scroll_height;
}
/* adjust vertical scroller if there's a horizontal scroller, to leave corner free */
if (scroll & V2D_SCROLL_VERTICAL) {
- /* just set y min/max for vertical scroller to y min/max of mask as appropriate */
if (scroll & (V2D_SCROLL_BOTTOM)) {
/* on bottom edge of region */
- v2d->vert.ymin = v2d->mask.ymin;
+ v2d->vert.ymin = v2d->hor.ymax;
}
else if (scroll & V2D_SCROLL_TOP) {
/* on upper edge of region */
- v2d->vert.ymax = v2d->mask.ymax;
+ v2d->vert.ymax = v2d->hor.ymin;
}
}
}
@@ -357,6 +358,11 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
/* set masks (always do), but leave scroller scheck to totrect_set */
view2d_masks(v2d, 0);
+ if (do_init) {
+ /* Visible by default. */
+ v2d->alpha_hor = v2d->alpha_vert = 255;
+ }
+
/* set 'tot' rect before setting cur? */
/* XXX confusing stuff here still - I made this function not check scroller hide - that happens in totrect_set */
if (tot_changed)
@@ -813,7 +819,7 @@ void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
}
/* region possibly changed, so refresh */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_no_rebuild(ar);
}
}
}
@@ -839,7 +845,7 @@ void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
}
/* region possibly changed, so refresh */
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_no_rebuild(ar);
}
}
}
@@ -1107,9 +1113,6 @@ void UI_view2d_view_ortho(View2D *v2d)
/* set matrix on all appropriate axes */
wmOrtho2(curmasked.xmin, curmasked.xmax, curmasked.ymin, curmasked.ymax);
-
- /* XXX is this necessary? */
- glLoadIdentity();
}
/**
@@ -1137,9 +1140,6 @@ void UI_view2d_view_orthoSpecial(ARegion *ar, View2D *v2d, const bool xaxis)
wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, -yofs, ar->winy - yofs);
else
wmOrtho2(-xofs, ar->winx - xofs, curmasked.ymin - yofs, curmasked.ymax - yofs);
-
- /* XXX is this necessary? */
- glLoadIdentity();
}
@@ -1151,7 +1151,7 @@ void UI_view2d_view_restore(const bContext *C)
int height = BLI_rcti_size_y(&ar->winrct) + 1;
wmOrtho2(0.0f, (float)width, 0.0f, (float)height);
- glLoadIdentity();
+ gpuLoadIdentity();
// ED_region_pixelspace(CTX_wm_region(C));
}
@@ -1305,12 +1305,45 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
{
float vec1[2], vec2[2];
int a, step;
+ int vertical_minor_step = (BLI_rcti_size_x(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC),
+ horizontal_major_step = (BLI_rcti_size_y(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC);
+ unsigned char grid_line_color[3];
/* check for grid first, as it may not exist */
if (grid == NULL)
return;
- glBegin(GL_LINES);
+ /* Count the needed vertices for the gridlines */
+ unsigned vertex_count = 0;
+ if (flag & V2D_VERTICAL_LINES) {
+ /* vertical lines */
+ vertex_count += 2 * vertical_minor_step; /* minor gridlines */
+ vertex_count += 2 * (vertical_minor_step + 2); /* major gridlines */
+ }
+ if (flag & V2D_HORIZONTAL_LINES) {
+ /* horizontal lines */
+ vertex_count += 2 * (horizontal_major_step + 1); /* major gridlines */
+
+ /* fine lines */
+ if (flag & V2D_HORIZONTAL_FINELINES)
+ vertex_count += 2 * (horizontal_major_step + 1);
+ }
+ /* axes */
+ if (flag & V2D_HORIZONTAL_AXIS)
+ vertex_count += 2;
+ if (flag & V2D_VERTICAL_AXIS)
+ vertex_count += 2;
+
+ /* If there is nothing to render, exit early */
+ if (vertex_count == 0)
+ return;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GWN_PRIM_LINES, vertex_count);
/* vertical lines */
if (flag & V2D_VERTICAL_LINES) {
@@ -1320,24 +1353,31 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
vec2[1] = v2d->cur.ymax;
/* minor gridlines */
- step = (BLI_rcti_size_x(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC);
- UI_ThemeColor(TH_GRID);
+ step = vertical_minor_step;
+ if (step != 0) {
+ UI_GetThemeColor3ubv(TH_GRID, grid_line_color);
- for (a = 0; a < step; a++) {
- glVertex2fv(vec1);
- glVertex2fv(vec2);
+ for (a = 0; a < step; a++) {
+ immSkipAttrib(color);
+ immVertex2fv(pos, vec1);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
- vec2[0] = vec1[0] += grid->dx;
+ vec2[0] = vec1[0] += grid->dx;
+ }
}
/* major gridlines */
vec2[0] = vec1[0] -= 0.5f * grid->dx;
- UI_ThemeColorShade(TH_GRID, 16);
+
+ UI_GetThemeColorShade3ubv(TH_GRID, 16, grid_line_color);
step++;
for (a = 0; a <= step; a++) {
- glVertex2fv(vec1);
- glVertex2fv(vec2);
+ immSkipAttrib(color);
+ immVertex2fv(pos, vec1);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
vec2[0] = vec1[0] -= grid->dx;
}
@@ -1350,12 +1390,15 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
vec1[0] = grid->startx;
vec2[0] = v2d->cur.xmax;
- step = (BLI_rcti_size_y(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC);
+ step = horizontal_major_step;
+
+ UI_GetThemeColor3ubv(TH_GRID, grid_line_color);
- UI_ThemeColor(TH_GRID);
for (a = 0; a <= step; a++) {
- glVertex2fv(vec1);
- glVertex2fv(vec2);
+ immSkipAttrib(color);
+ immVertex2fv(pos, vec1);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
vec2[1] = vec1[1] += grid->dy;
}
@@ -1365,10 +1408,12 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
step++;
if (flag & V2D_HORIZONTAL_FINELINES) {
- UI_ThemeColorShade(TH_GRID, 16);
+ UI_GetThemeColorShade3ubv(TH_GRID, 16, grid_line_color);
for (a = 0; a < step; a++) {
- glVertex2fv(vec1);
- glVertex2fv(vec2);
+ immSkipAttrib(color);
+ immVertex2fv(pos, vec1);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
vec2[1] = vec1[1] -= grid->dy;
}
@@ -1376,7 +1421,7 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
}
/* Axes are drawn as darker lines */
- UI_ThemeColorShade(TH_GRID, -50);
+ UI_GetThemeColorShade3ubv(TH_GRID, -50, grid_line_color);
/* horizontal axis */
if (flag & V2D_HORIZONTAL_AXIS) {
@@ -1384,8 +1429,10 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
vec2[0] = v2d->cur.xmax;
vec1[1] = vec2[1] = 0.0f;
- glVertex2fv(vec1);
- glVertex2fv(vec2);
+ immSkipAttrib(color);
+ immVertex2fv(pos, vec1);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
}
/* vertical axis */
@@ -1394,91 +1441,157 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
vec2[1] = v2d->cur.ymax;
vec1[0] = vec2[0] = 0.0f;
- glVertex2fv(vec1);
- glVertex2fv(vec2);
+ immSkipAttrib(color);
+ immVertex2fv(pos, vec1);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
/* Draw a constant grid in given 2d-region */
void UI_view2d_constant_grid_draw(View2D *v2d, float step)
{
- float start;
+ float start_x, start_y;
+ int count_x, count_y;
- UI_ThemeColorShade(TH_BACK, -10);
+ start_x = v2d->cur.xmin;
+ if (start_x < 0.0)
+ start_x += -(float)fmod(v2d->cur.xmin, step);
+ else
+ start_x += (step - (float)fmod(v2d->cur.xmin, step));
- start = v2d->cur.xmin - (float)fmod(v2d->cur.xmin, step);
+ if (start_x > v2d->cur.xmax)
+ count_x = 0;
+ else
+ count_x = (v2d->cur.xmax - start_x) / step + 1;
- glBegin(GL_LINES);
- for (; start < v2d->cur.xmax; start += step) {
- glVertex2f(start, v2d->cur.ymin);
- glVertex2f(start, v2d->cur.ymax);
- }
+ start_y = v2d->cur.ymin;
+ if (start_y < 0.0)
+ start_y += -(float)fmod(v2d->cur.ymin, step);
+ else
+ start_y += (step - (float)fabs(fmod(v2d->cur.ymin, step)));
- start = v2d->cur.ymin - (float)fmod(v2d->cur.ymin, step);
- for (; start < v2d->cur.ymax; start += step) {
- glVertex2f(v2d->cur.xmin, start);
- glVertex2f(v2d->cur.xmax, start);
- }
+ if (start_y > v2d->cur.ymax)
+ count_y = 0;
+ else
+ count_y = (v2d->cur.ymax - start_y) / step + 1;
- /* X and Y axis */
- UI_ThemeColorShade(TH_BACK, -18);
- glVertex2f(0.0f, v2d->cur.ymin);
- glVertex2f(0.0f, v2d->cur.ymax);
- glVertex2f(v2d->cur.xmin, 0.0f);
- glVertex2f(v2d->cur.xmax, 0.0f);
+ if (count_x > 0 || count_y > 0) {
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ float theme_color[3];
+
+ UI_GetThemeColorShade3fv(TH_BACK, -10, theme_color);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GWN_PRIM_LINES, count_x * 2 + count_y * 2 + 4);
+
+ immAttrib3fv(color, theme_color);
+ for (int i = 0; i < count_x ; start_x += step, i++) {
+ immVertex2f(pos, start_x, v2d->cur.ymin);
+ immVertex2f(pos, start_x, v2d->cur.ymax);
+ }
+
+ for (int i = 0; i < count_y; start_y += step, i++) {
+ immVertex2f(pos, v2d->cur.xmin, start_y);
+ immVertex2f(pos, v2d->cur.xmax, start_y);
+ }
+
+ /* X and Y axis */
+ UI_GetThemeColorShade3fv(TH_BACK, -18, theme_color);
- glEnd();
+ immAttrib3fv(color, theme_color);
+ immVertex2f(pos, 0.0f, v2d->cur.ymin);
+ immVertex2f(pos, 0.0f, v2d->cur.ymax);
+ immVertex2f(pos, v2d->cur.xmin, 0.0f);
+ immVertex2f(pos, v2d->cur.xmax, 0.0f);
+
+ immEnd();
+ immUnbindProgram();
+ }
}
/* Draw a multi-level grid in given 2d-region */
void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_size, int totlevels)
{
+ /* Exit if there is nothing to draw */
+ if (totlevels == 0)
+ return;
+
int offset = -10;
float lstep = step;
- int level;
+ unsigned char grid_line_color[3];
- glLineWidth(1.0f);
- for (level = 0; level < totlevels; ++level) {
- int i;
- float start;
+ /* Make an estimate of at least how many vertices will be needed */
+ unsigned vertex_count = 4;
+ vertex_count += 2 * ((int)((v2d->cur.xmax - v2d->cur.xmin) / lstep) + 1);
+ vertex_count += 2 * ((int)((v2d->cur.ymax - v2d->cur.ymin) / lstep) + 1);
- UI_ThemeColorShade(colorid, offset);
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
- i = (v2d->cur.xmin >= 0.0f ? -(int)(-v2d->cur.xmin / lstep) : (int)(v2d->cur.xmin / lstep));
- start = i * lstep;
+ GPU_line_width(1.0f);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBeginAtMost(GWN_PRIM_LINES, vertex_count);
+
+ for (int level = 0; level < totlevels; ++level) {
+ UI_GetThemeColorShade3ubv(colorid, offset, grid_line_color);
+
+ int i = (int)(v2d->cur.xmin / lstep);
+ if (v2d->cur.xmin > 0.0f)
+ i++;
+ float start = i * lstep;
- glBegin(GL_LINES);
for (; start < v2d->cur.xmax; start += lstep, ++i) {
if (i == 0 || (level < totlevels - 1 && i % level_size == 0))
continue;
- glVertex2f(start, v2d->cur.ymin);
- glVertex2f(start, v2d->cur.ymax);
+
+ immSkipAttrib(color);
+ immVertex2f(pos, start, v2d->cur.ymin);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2f(pos, start, v2d->cur.ymax);
}
- i = (v2d->cur.ymin >= 0.0f ? -(int)(-v2d->cur.ymin / lstep) : (int)(v2d->cur.ymin / lstep));
+ i = (int)(v2d->cur.ymin / lstep);
+ if (v2d->cur.ymin > 0.0f)
+ i++;
start = i * lstep;
for (; start < v2d->cur.ymax; start += lstep, ++i) {
if (i == 0 || (level < totlevels - 1 && i % level_size == 0))
continue;
- glVertex2f(v2d->cur.xmin, start);
- glVertex2f(v2d->cur.xmax, start);
- }
-
- /* X and Y axis */
- UI_ThemeColorShade(colorid, offset - 8);
- glVertex2f(0.0f, v2d->cur.ymin);
- glVertex2f(0.0f, v2d->cur.ymax);
- glVertex2f(v2d->cur.xmin, 0.0f);
- glVertex2f(v2d->cur.xmax, 0.0f);
- glEnd();
+ immSkipAttrib(color);
+ immVertex2f(pos, v2d->cur.xmin, start);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2f(pos, v2d->cur.xmax, start);
+ }
lstep *= level_size;
offset -= 6;
}
+
+ /* X and Y axis */
+ UI_GetThemeColorShade3ubv(colorid, -18 + ((totlevels - 1) * -6), grid_line_color);
+
+ immSkipAttrib(color);
+ immVertex2f(pos, 0.0f, v2d->cur.ymin);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2f(pos, 0.0f, v2d->cur.ymax);
+
+ immSkipAttrib(color);
+ immVertex2f(pos, v2d->cur.xmin, 0.0f);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2f(pos, v2d->cur.xmax, 0.0f);
+
+ immEnd();
+ immUnbindProgram();
}
/* the price we pay for not exposting structs :( */
@@ -1534,11 +1647,14 @@ View2DScrollers *UI_view2d_scrollers_calc(
/* scrollers is allocated here... */
scrollers = MEM_callocN(sizeof(View2DScrollers), "View2DScrollers");
+ /* Always update before drawing (for dynamically sized scrollers). */
+ view2d_masks(v2d, false);
+
vert = v2d->vert;
hor = v2d->hor;
/* slider rects need to be smaller than region */
- smaller = (int)(0.2f * U.widget_unit);
+ smaller = (int)(0.1f * U.widget_unit);
hor.xmin += smaller;
hor.xmax -= smaller;
if (scroll & V2D_SCROLL_BOTTOM)
@@ -1698,9 +1814,15 @@ static void scroll_printstr(Scene *scene, float x, float y, float val, int power
/* Draw scrollbars in the given 2d-region */
void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *vs)
{
+ bTheme *btheme = UI_GetTheme();
Scene *scene = CTX_data_scene(C);
rcti vert, hor;
- int scroll = view2d_scroll_mapped(v2d->scroll);
+ const int scroll = view2d_scroll_mapped(v2d->scroll);
+ const char emboss_alpha = btheme->tui.widget_emboss[3];
+ unsigned char scrollers_back_color[4];
+
+ /* Color for scrollbar backs */
+ UI_GetThemeColor4ubv(TH_BACK, scrollers_back_color);
/* make copies of rects for less typing */
vert = vs->vert;
@@ -1708,11 +1830,10 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
/* horizontal scrollbar */
if (scroll & V2D_SCROLL_HORIZONTAL) {
- bTheme *btheme = UI_GetTheme();
uiWidgetColors wcol = btheme->tui.wcol_scroll;
+ const float alpha_fac = v2d->alpha_hor / 255.0f;
rcti slider;
int state;
- unsigned char col[4];
slider.xmin = vs->hor_min;
slider.xmax = vs->hor_max;
@@ -1721,6 +1842,11 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
state = (v2d->scroll_ui & V2D_SCROLL_H_ACTIVE) ? UI_SCROLL_PRESSED : 0;
+ wcol.inner[3] *= alpha_fac;
+ wcol.item[3] *= alpha_fac;
+ wcol.outline[3] *= alpha_fac;
+ btheme->tui.widget_emboss[3] *= alpha_fac; /* will be reset later */
+
/* show zoom handles if:
* - zooming on x-axis is allowed (no scroll otherwise)
* - slider bubble is large enough (no overdraw confusion)
@@ -1735,17 +1861,11 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
state |= UI_SCROLL_ARROWS;
}
- /* clean rect behind slider, but not with transparent background */
- UI_GetThemeColor4ubv(TH_BACK, col);
- if (col[3] == 255) {
- glColor3ub(col[0], col[1], col[2]);
- glRecti(v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax);
- }
-
UI_draw_widget_scroll(&wcol, &hor, &slider, state);
/* scale indicators */
if ((scroll & V2D_SCROLL_SCALE_HORIZONTAL) && (vs->grid)) {
+ const int font_id = BLF_default();
View2DGrid *grid = vs->grid;
float fac, dfac, fac2, val;
@@ -1760,7 +1880,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
dfac = dfac * BLI_rcti_size_x(&hor);
/* set starting value, and text color */
- UI_ThemeColor(TH_TEXT);
+ UI_FontThemeColor(font_id, TH_TEXT);
val = grid->startx;
/* if we're clamping to whole numbers only, make sure entries won't be repeated */
@@ -1777,6 +1897,8 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
if (dfac > 0.0f) {
float h = 0.1f * UI_UNIT_Y + (float)(hor.ymin);
+ BLF_batch_draw_begin();
+
for (; fac < hor.xmax - 0.5f * U.widget_unit; fac += dfac, val += grid->dx) {
/* make prints look nicer for scrollers */
@@ -1803,17 +1925,18 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
break;
}
}
+
+ BLF_batch_draw_end();
}
}
}
/* vertical scrollbar */
if (scroll & V2D_SCROLL_VERTICAL) {
- bTheme *btheme = UI_GetTheme();
uiWidgetColors wcol = btheme->tui.wcol_scroll;
rcti slider;
+ const float alpha_fac = v2d->alpha_vert / 255.0f;
int state;
- unsigned char col[4];
slider.xmin = vert.xmin;
slider.xmax = vert.xmax;
@@ -1822,6 +1945,11 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
state = (v2d->scroll_ui & V2D_SCROLL_V_ACTIVE) ? UI_SCROLL_PRESSED : 0;
+ wcol.inner[3] *= alpha_fac;
+ wcol.item[3] *= alpha_fac;
+ wcol.outline[3] *= alpha_fac;
+ btheme->tui.widget_emboss[3] *= alpha_fac; /* will be reset later */
+
/* show zoom handles if:
* - zooming on y-axis is allowed (no scroll otherwise)
* - slider bubble is large enough (no overdraw confusion)
@@ -1836,13 +1964,6 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
state |= UI_SCROLL_ARROWS;
}
- /* clean rect behind slider, but not with transparent background */
- UI_GetThemeColor4ubv(TH_BACK, col);
- if (col[3] == 255) {
- glColor3ub(col[0], col[1], col[2]);
- glRecti(v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax);
- }
-
UI_draw_widget_scroll(&wcol, &vert, &slider, state);
@@ -1864,7 +1985,8 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
dfac = dfac * BLI_rcti_size_y(&vert);
/* set starting value, and text color */
- UI_ThemeColor(TH_TEXT);
+ const int font_id = BLF_default();
+ UI_FontThemeColor(font_id, TH_TEXT);
val = grid->starty;
/* if vertical clamping (to whole numbers) is used (i.e. in Sequencer), apply correction */
@@ -1873,9 +1995,8 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
/* draw vertical steps */
if (dfac > 0.0f) {
-
- BLF_rotation_default(M_PI_2);
- BLF_enable_default(BLF_ROTATION);
+ BLF_rotation(font_id, M_PI_2);
+ BLF_enable(font_id, BLF_ROTATION);
for (; fac < vert.ymax - 10; fac += dfac, val += grid->dy) {
@@ -1886,11 +2007,13 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
scroll_printstr(scene, (float)(vert.xmax) - 2.0f, fac, val, grid->powery, vs->yunits, 'v');
}
- BLF_disable_default(BLF_ROTATION);
+ BLF_disable(font_id, BLF_ROTATION);
}
}
}
+ /* Was changed above, so reset. */
+ btheme->tui.widget_emboss[3] = emboss_alpha;
}
/* free temporary memory used for drawing scrollers */
@@ -2299,9 +2422,8 @@ void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac)
* - 'v' = in vertical scroller.
* - 0 = not in scroller.
*/
-short UI_view2d_mouse_in_scrollers(const bContext *C, View2D *v2d, int x, int y)
+short UI_view2d_mouse_in_scrollers(const ARegion *ar, View2D *v2d, int x, int y)
{
- ARegion *ar = CTX_wm_region(C);
int co[2];
int scroll = view2d_scroll_mapped(v2d->scroll);
@@ -2410,7 +2532,8 @@ void UI_view2d_text_cache_draw(ARegion *ar)
int col_pack_prev = 0;
/* investigate using BLF_ascender() */
- const float default_height = g_v2d_strings ? BLF_height_default("28", 3) : 0.0f;
+ const int font_id = BLF_default();
+ const float default_height = g_v2d_strings ? BLF_height(font_id, "28", 3) : 0.0f;
wmOrtho2_region_pixelspace(ar);
@@ -2421,7 +2544,7 @@ void UI_view2d_text_cache_draw(ARegion *ar)
if (yofs < 1) yofs = 1;
if (col_pack_prev != v2s->col.pack) {
- glColor3ubv(v2s->col.ub);
+ BLF_color3ubv(font_id, v2s->col.ub);
col_pack_prev = v2s->col.pack;
}
@@ -2430,12 +2553,11 @@ void UI_view2d_text_cache_draw(ARegion *ar)
(float)(v2s->mval[0] + xofs), (float)(v2s->mval[1] + yofs), 0.0,
v2s->str, BLF_DRAW_STR_DUMMY_MAX);
else {
- BLF_clipping_default(v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4);
- BLF_enable_default(BLF_CLIPPING);
- BLF_draw_default(
- v2s->rect.xmin + xofs, v2s->rect.ymin + yofs, 0.0f,
- v2s->str, BLF_DRAW_STR_DUMMY_MAX);
- BLF_disable_default(BLF_CLIPPING);
+ BLF_enable(font_id, BLF_CLIPPING);
+ BLF_clipping(font_id, v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4);
+ BLF_draw_default(v2s->rect.xmin + xofs, v2s->rect.ymin + yofs, 0.0f,
+ v2s->str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_disable(font_id, BLF_CLIPPING);
}
}
g_v2d_strings = NULL;
@@ -2444,11 +2566,6 @@ void UI_view2d_text_cache_draw(ARegion *ar)
BLI_memarena_free(g_v2d_strings_arena);
g_v2d_strings_arena = NULL;
}
-
- // glMatrixMode(GL_PROJECTION);
- // glPopMatrix();
- // glMatrixMode(GL_MODELVIEW);
- // glPopMatrix();
}
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 3cad2167cfa..dfc401c1635 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -33,6 +33,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -169,18 +170,13 @@ static void view_pan_apply_ex(bContext *C, v2dViewPanData *vpd, float dx, float
/* validate that view is in valid configuration after this operation */
UI_view2d_curRect_validate(v2d);
+ /* don't rebuild full tree in outliner, since we're just changing our view */
+ ED_region_tag_redraw_no_rebuild(vpd->ar);
+
/* request updates to be done... */
- ED_region_tag_redraw(vpd->ar);
WM_event_add_mousemove(C);
UI_view2d_sync(vpd->sc, vpd->sa, v2d, V2D_LOCK_COPY);
-
- /* exceptions */
- if (vpd->sa->spacetype == SPACE_OUTLINER) {
- /* don't rebuild full tree, since we're just changing our view */
- SpaceOops *soops = vpd->sa->spacedata.first;
- soops->storeflag |= SO_TREESTORE_REDRAW;
- }
}
static void view_pan_apply(bContext *C, wmOperator *op)
@@ -642,6 +638,7 @@ static void view_zoomstep_apply_ex(
View2D *v2d = &ar->v2d;
const rctf cur_old = v2d->cur;
float dx, dy;
+ const int snap_test = ED_region_snap_size_test(ar);
/* calculate amount to move view by, ensuring symmetry so the
* old zoom level is restored after zooming back the same amount
@@ -726,8 +723,14 @@ static void view_zoomstep_apply_ex(
/* validate that view is in valid configuration after this operation */
UI_view2d_curRect_validate(v2d);
+ if (ED_region_snap_size_apply(ar, snap_test)) {
+ ScrArea *sa = CTX_wm_area(C);
+ ED_area_tag_redraw(sa);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ }
+
/* request updates to be done... */
- ED_region_tag_redraw(vzd->ar);
+ ED_region_tag_redraw_no_rebuild(vzd->ar);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
@@ -902,6 +905,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
v2dViewZoomData *vzd = op->customdata;
View2D *v2d = vzd->v2d;
float dx, dy;
+ const int snap_test = ED_region_snap_size_test(vzd->ar);
/* get amount to move view by */
dx = RNA_float_get(op->ptr, "deltax");
@@ -966,8 +970,14 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
/* validate that view is in valid configuration after this operation */
UI_view2d_curRect_validate(v2d);
+ if (ED_region_snap_size_apply(vzd->ar, snap_test)) {
+ ScrArea *sa = CTX_wm_area(C);
+ ED_area_tag_redraw(sa);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ }
+
/* request updates to be done... */
- ED_region_tag_redraw(vzd->ar);
+ ED_region_tag_redraw_no_rebuild(vzd->ar);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
@@ -1488,7 +1498,7 @@ void UI_view2d_smooth_view(
v2d->cur = sms.new_cur;
UI_view2d_curRect_validate(v2d);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_no_rebuild(ar);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
}
@@ -1532,7 +1542,7 @@ static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w
UI_view2d_curRect_validate(v2d);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_no_rebuild(ar);
if (v2d->sms == NULL) {
UI_view2d_zoom_cache_reset();
@@ -1668,6 +1678,21 @@ static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_
return SCROLLHANDLE_BAR;
}
+static bool scroller_activate_poll(bContext *C)
+{
+ if (!view2d_poll(C)) {
+ return false;
+ }
+
+ wmWindow *win = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = &ar->v2d;
+ wmEvent *event = win->eventstate;
+
+ /* check if mouse in scrollbars, if they're enabled */
+ return (UI_view2d_mouse_in_scrollers(ar, v2d, event->x, event->y) != 0);
+}
+
/* initialize customdata for scroller manipulation operator */
static void scroller_activate_init(bContext *C, wmOperator *op, const wmEvent *event, short in_scroller)
{
@@ -1746,7 +1771,7 @@ static void scroller_activate_init(bContext *C, wmOperator *op, const wmEvent *e
}
UI_view2d_scrollers_free(scrollers);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw_no_rebuild(ar);
}
/* cleanup temp customdata */
@@ -1760,7 +1785,7 @@ static void scroller_activate_exit(bContext *C, wmOperator *op)
MEM_freeN(op->customdata);
op->customdata = NULL;
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
}
}
@@ -1822,7 +1847,7 @@ static void scroller_activate_apply(bContext *C, wmOperator *op)
UI_view2d_curRect_validate(v2d);
/* request updates to be done... */
- ED_region_tag_redraw(vsm->ar);
+ ED_region_tag_redraw_no_rebuild(vsm->ar);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
@@ -1906,7 +1931,7 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent *
short in_scroller = 0;
/* check if mouse in scrollbars, if they're enabled */
- in_scroller = UI_view2d_mouse_in_scrollers(C, v2d, event->x, event->y);
+ in_scroller = UI_view2d_mouse_in_scrollers(ar, v2d, event->x, event->y);
/* if in a scroller, init customdata then set modal handler which will catch mousedown to start doing useful stuff */
if (in_scroller) {
@@ -2000,7 +2025,7 @@ static void VIEW2D_OT_scroller_activate(wmOperatorType *ot)
ot->modal = scroller_activate_modal;
ot->cancel = scroller_activate_cancel;
- ot->poll = view2d_poll;
+ ot->poll = scroller_activate_poll;
}
/* ********************************************************* */
@@ -2012,6 +2037,7 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op))
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
int winx, winy;
+ const int snap_test = ED_region_snap_size_test(ar);
/* zoom 1.0 */
winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
@@ -2046,6 +2072,12 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op))
/* validate that view is in valid configuration after this operation */
UI_view2d_curRect_validate(v2d);
+ if (ED_region_snap_size_apply(ar, snap_test)) {
+ ScrArea *sa = CTX_wm_area(C);
+ ED_area_tag_redraw(sa);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ }
+
/* request updates to be done... */
ED_region_tag_redraw(ar);
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);