Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/interface/interface_regions.c
| Context not available. | |||||
| #define MENU_TOP 8 | #define MENU_TOP 8 | ||||
| #define MENU_PADDING (int)(0.2f * UI_UNIT_Y) | #define MENU_PADDING (int)(0.2f * UI_UNIT_Y) | ||||
| #define TOOLTIP_PADDING (int)(1.3f * UI_UNIT_Y) | |||||
| static int rna_property_enum_step(const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int direction) | static int rna_property_enum_step(const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int direction) | ||||
| { | { | ||||
| EnumPropertyItem *item_array; | EnumPropertyItem *item_array; | ||||
| Context not available. | |||||
| typedef enum { | typedef enum { | ||||
| UI_TIP_LC_MAIN, | UI_TIP_LC_MAIN, | ||||
| UI_TIP_LC_SUBMENU, | |||||
campbellbarton: Name SUBMENU isnt very helpful/informative. | |||||
| UI_TIP_LC_ACTIVE, | |||||
| UI_TIP_LC_NORMAL, | UI_TIP_LC_NORMAL, | ||||
| UI_TIP_LC_PYTHON, | UI_TIP_LC_PYTHON, | ||||
| UI_TIP_LC_ALERT, | UI_TIP_LC_ALERT | ||||
| UI_TIP_LC_SUBMENU | |||||
| } uiTooltipLineColor; | } uiTooltipLineColor; | ||||
| #define UI_TIP_LC_MAX 5 | #define UI_TIP_LC_MAX 6 | ||||
| enum { | |||||
Not Done Inline ActionsUI_TIP_HEADER excludes UI_TIP_PYTHON, these shouldn't be flags. campbellbarton: UI_TIP_HEADER excludes UI_TIP_PYTHON, these shouldn't be flags. | |||||
| UI_TIP_HEADER = (1 << 0), | |||||
| UI_TIP_ROW_PADDING = (1 << 1), | |||||
| }; | |||||
| #define MAX_TOOLTIP_LINES 8 | #define MAX_TOOLTIP_LINES 8 | ||||
| typedef struct uiTooltipData { | typedef struct uiTooltipData { | ||||
| rcti bbox; | rcti bbox; | ||||
| uiFontStyle fstyle; | uiFontStyle fstyle; | ||||
| char lines[MAX_TOOLTIP_LINES][512]; | char lines[MAX_TOOLTIP_LINES][512]; | ||||
| char header[512]; | |||||
| char active_info[512]; | |||||
| uiTooltipLineColor color_id[MAX_TOOLTIP_LINES]; | uiTooltipLineColor color_id[MAX_TOOLTIP_LINES]; | ||||
| int flag[MAX_TOOLTIP_LINES]; | |||||
| int totline; | int totline; | ||||
| int toth, spaceh, lineh; | int toth, lineh, linew; | ||||
| } uiTooltipData; | } uiTooltipData; | ||||
| static void rgb_tint(float col[3], | static void rgb_tint(float col[3], | ||||
| Context not available. | |||||
| float tip_colors[UI_TIP_LC_MAX][3]; | float tip_colors[UI_TIP_LC_MAX][3]; | ||||
| float *main_color = tip_colors[UI_TIP_LC_MAIN]; /* the color from the theme */ | float *main_color = tip_colors[UI_TIP_LC_MAIN]; /* the color from the theme */ | ||||
| float *submenu_color = tip_colors[UI_TIP_LC_SUBMENU]; | |||||
| float *active_color = tip_colors[UI_TIP_LC_ACTIVE]; | |||||
| float *normal_color = tip_colors[UI_TIP_LC_NORMAL]; | float *normal_color = tip_colors[UI_TIP_LC_NORMAL]; | ||||
| float *python_color = tip_colors[UI_TIP_LC_PYTHON]; | float *python_color = tip_colors[UI_TIP_LC_PYTHON]; | ||||
| float *alert_color = tip_colors[UI_TIP_LC_ALERT]; | float *alert_color = tip_colors[UI_TIP_LC_ALERT]; | ||||
| float *submenu_color = tip_colors[UI_TIP_LC_SUBMENU]; | |||||
| float background_color[3]; | float background_color[3]; | ||||
| float tone_bg; | float tone_bg; | ||||
| Context not available. | |||||
| /* calculate normal_color */ | /* calculate normal_color */ | ||||
| rgb_uchar_to_float(main_color, (const unsigned char *)theme->text); | rgb_uchar_to_float(main_color, (const unsigned char *)theme->text); | ||||
| copy_v3_v3(submenu_color, main_color); | |||||
| copy_v3_v3(active_color, main_color); | |||||
| copy_v3_v3(normal_color, main_color); | copy_v3_v3(normal_color, main_color); | ||||
| copy_v3_v3(python_color, main_color); | copy_v3_v3(python_color, main_color); | ||||
| copy_v3_v3(alert_color, main_color); | copy_v3_v3(alert_color, main_color); | ||||
| copy_v3_v3(submenu_color, main_color); | |||||
| /* find the brightness difference between background and text colors */ | /* find the brightness difference between background and text colors */ | ||||
| tone_bg = rgb_to_grayscale(background_color); | tone_bg = rgb_to_grayscale(background_color); | ||||
| /* tone_fg = rgb_to_grayscale(main_color); */ | /* tone_fg = rgb_to_grayscale(main_color); */ | ||||
| rgb_tint(normal_color, 0.0f, 0.0f, tone_bg, 0.3f); /* a shade darker (to bg) */ | /* mix the colors */ | ||||
| rgb_tint(python_color, 0.666f, 0.25f, tone_bg, 0.3f); /* blue */ | rgb_tint(submenu_color, 0.0f, 0.0f, tone_bg, 0.2f); /* light grey */ | ||||
| rgb_tint(alert_color, 0.0f, 0.8f, tone_bg, 0.1f); /* bright red */ | rgb_tint(active_color, 0.6f, 0.2f, tone_bg, 0.2f); /* light blue */ | ||||
| rgb_tint(submenu_color, 0.0f, 0.0f, tone_bg, 0.3f); /* a shade darker (to bg) */ | rgb_tint(normal_color, 0.0f, 0.0f, tone_bg, 0.5f); /* grey */ | ||||
| rgb_tint(python_color, 0.0f, 0.0f, tone_bg, 0.7f); /* dark grey */ | |||||
| rgb_tint(alert_color, 0.0f, 0.8f, tone_bg, 0.1f); /* red */ | |||||
| /* draw text */ | /* draw text */ | ||||
| uiStyleFontSet(&data->fstyle); | uiStyleFontSet(&data->fstyle); | ||||
| bbox.ymax = bbox.ymax - 0.5f * (BLI_rcti_size_y(&bbox) - data->toth); | bbox.xmin += 0.5f * TOOLTIP_PADDING; /* add padding to the text */ | ||||
| bbox.ymax -= 0.5f * (BLI_rcti_size_y(&bbox) - data->toth); | |||||
| bbox.ymin = bbox.ymax - data->lineh; | bbox.ymin = bbox.ymax - data->lineh; | ||||
| for (i = 0; i < data->totline; i++) { | for (i = 0; i < data->totline; i++) { | ||||
| glColor3fv(tip_colors[data->color_id[i]]); | if (data->flag[i] & UI_TIP_HEADER) { | ||||
Not Done Inline ActionsOverrides shouldnt change source data. campbellbarton: Overrides shouldnt change source data. | |||||
| uiStyleFontDraw(&data->fstyle, &bbox, data->lines[i]); | float xofs; | ||||
| bbox.ymin -= data->lineh + data->spaceh; | |||||
| bbox.ymax -= data->lineh + data->spaceh; | // BLF_size(data->fstyle.uifont_id, 12 * U.pixelsize, U.dpi); | ||||
| xofs = BLF_width(data->fstyle.uifont_id, data->header, sizeof(data->header)); | |||||
| data->fstyle.bold = 0; | |||||
| // data->fstyle.points = 12; | |||||
| data->fstyle.kerning = 1; | |||||
| BLF_enable(data->fstyle.uifont_id, BLF_SHADOW); | |||||
| BLF_shadow(data->fstyle.uifont_id, 1, 0.9f, 0.9f, 0.9f, 1.0f); | |||||
| BLF_shadow_offset(data->fstyle.uifont_id, 0, 0); | |||||
| /* draw header and active data, is done here to be able to change color */ | |||||
| glColor3fv(tip_colors[UI_TIP_LC_MAIN]); | |||||
Not Done Inline Actionshard-coded values here isnt great, should use UI_TIP_LC_ACTIVE, also. fstyle can be made to enable shadow campbellbarton: hard-coded values here isnt great, should use UI_TIP_LC_ACTIVE, also. fstyle can be made to… | |||||
| uiStyleFontDraw(&data->fstyle, &bbox, data->header); | |||||
| bbox.xmin += xofs; | |||||
| BLF_shadow(data->fstyle.uifont_id, 1, 0.3f, 0.6f, 0.7f, 0.9f); | |||||
| glColor3fv(tip_colors[UI_TIP_LC_ACTIVE]); | |||||
| uiStyleFontDraw(&data->fstyle, &bbox, data->active_info); | |||||
| BLF_disable(data->fstyle.uifont_id, BLF_SHADOW); | |||||
Not Done Inline Actionsmodifying style directly is bad practice. use a copy. campbellbarton: modifying style directly is bad practice. use a copy. | |||||
Not Done Inline ActionsThis fails for high-resolution displays (where U.pixelsize == 2) campbellbarton: This fails for high-resolution displays (where `U.pixelsize == 2`) | |||||
| bbox.xmin -= xofs; | |||||
| } | |||||
| else { | |||||
| data->fstyle.bold = 0; | |||||
| // data->fstyle.points = 11; | |||||
| data->fstyle.kerning = 0; | |||||
| glColor3fv(tip_colors[data->color_id[i]]); | |||||
| uiStyleFontDraw(&data->fstyle, &bbox, data->lines[i]); | |||||
| } | |||||
| if (data->flag[i + 1] & UI_TIP_ROW_PADDING) { | |||||
| bbox.ymax -= data->lineh * 1.3f; | |||||
| bbox.ymin -= data->lineh * 1.3f; | |||||
| } | |||||
| else { | |||||
| bbox.ymax -= data->lineh; | |||||
| bbox.ymin -= data->lineh; | |||||
| } | |||||
| } | } | ||||
| if (multisample_enabled) | if (multisample_enabled) | ||||
| Context not available. | |||||
| /* aspect values that shrink text are likely unreadable */ | /* aspect values that shrink text are likely unreadable */ | ||||
| const float aspect = min_ff(1.0f, but->block->aspect); | const float aspect = min_ff(1.0f, but->block->aspect); | ||||
| float fonth, fontw; | float fonth, fontw; | ||||
| int winx /*, winy */, ofsx, ofsy, w, h, a; | int winx /*, winy */, w = 0, h, a; | ||||
| rctf rect_fl; | rctf rect_fl; | ||||
| rcti rect_i; | rcti rect_i; | ||||
| Context not available. | |||||
| uiButGetStrInfo(C, but, &but_tip, &enum_label, &enum_tip, &op_keymap, &prop_keymap, &rna_struct, &rna_prop, NULL); | uiButGetStrInfo(C, but, &but_tip, &enum_label, &enum_tip, &op_keymap, &prop_keymap, &rna_struct, &rna_prop, NULL); | ||||
| /* special case, enum rna buttons only have enum item description, | |||||
| * use general enum description too before the specific one */ | |||||
| /* Tip */ | /* Tip */ | ||||
| if (but_tip.strinfo) { | if (but_tip.strinfo) { | ||||
| /* Expanded Bit-flag enums have a specific way to select multiple... */ | BLI_strncpy(data->header, but_tip.strinfo, sizeof(data->lines[0])); | ||||
| if ((but->type & ROW) && but->rnaprop && RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG) { | if (enum_label.strinfo) { | ||||
| BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), | BLI_snprintf(data->header, sizeof(data->header), "%s: ", but_tip.strinfo); | ||||
| "%s %s", but_tip.strinfo, IFACE_("(Shift-click to select multiple)")); | BLI_strncpy(data->active_info, enum_label.strinfo, sizeof(data->lines[0])); | ||||
| } | } | ||||
| else { | data->flag[data->totline] |= UI_TIP_HEADER; | ||||
| BLI_strncpy(data->lines[data->totline], but_tip.strinfo, sizeof(data->lines[0])); | |||||
| } | |||||
| data->color_id[data->totline] = UI_TIP_LC_MAIN; | |||||
| data->totline++; | data->totline++; | ||||
| /* special case enum rna buttons */ | |||||
| if ((but->type & ROW) && but->rnaprop && RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG) { | |||||
| BLI_strncpy(data->lines[data->totline], IFACE_("(Shift-click to select multiple)"), sizeof(data->lines[0])); | |||||
| data->color_id[data->totline] = UI_TIP_LC_NORMAL; | |||||
| data->totline++; | |||||
| } | |||||
| } | } | ||||
| /* Enum item label & tip */ | /* Enum item label & tip */ | ||||
| if (enum_label.strinfo && enum_tip.strinfo) { | if (enum_tip.strinfo) { | ||||
| BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), | BLI_strncpy(data->lines[data->totline], enum_tip.strinfo, sizeof(data->lines[0])); | ||||
| "%s: %s", enum_label.strinfo, enum_tip.strinfo); | data->flag[data->totline] |= UI_TIP_ROW_PADDING; | ||||
| data->color_id[data->totline] = UI_TIP_LC_SUBMENU; | data->color_id[data->totline] = UI_TIP_LC_SUBMENU; | ||||
| data->totline++; | data->totline++; | ||||
| } | } | ||||
| Context not available. | |||||
| /* Op shortcut */ | /* Op shortcut */ | ||||
| if (op_keymap.strinfo) { | if (op_keymap.strinfo) { | ||||
| BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Shortcut: %s"), op_keymap.strinfo); | BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Shortcut: %s"), op_keymap.strinfo); | ||||
| data->color_id[data->totline] = UI_TIP_LC_NORMAL; | data->flag[data->totline] |= UI_TIP_ROW_PADDING; | ||||
| data->color_id[data->totline] = UI_TIP_LC_SUBMENU; | |||||
| data->totline++; | data->totline++; | ||||
| } | } | ||||
| /* Property context-toggle shortcut */ | /* Property context-toggle shortcut */ | ||||
| if (prop_keymap.strinfo) { | if (prop_keymap.strinfo) { | ||||
| BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Shortcut: %s"), prop_keymap.strinfo); | BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Shortcut: %s"), prop_keymap.strinfo); | ||||
| data->color_id[data->totline] = UI_TIP_LC_NORMAL; | data->flag[data->totline] |= UI_TIP_ROW_PADDING; | ||||
| data->color_id[data->totline] = UI_TIP_LC_SUBMENU; | |||||
| data->totline++; | data->totline++; | ||||
| } | } | ||||
| Context not available. | |||||
| ui_get_but_string(but, buf, sizeof(buf)); | ui_get_but_string(but, buf, sizeof(buf)); | ||||
| if (buf[0]) { | if (buf[0]) { | ||||
| BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Value: %s"), buf); | BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Value: %s"), buf); | ||||
| data->color_id[data->totline] = UI_TIP_LC_NORMAL; | data->flag[data->totline] |= UI_TIP_ROW_PADDING; | ||||
| data->color_id[data->totline] = UI_TIP_LC_SUBMENU; | |||||
| data->totline++; | data->totline++; | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| /* operator info */ | /* operator info */ | ||||
| if ((U.flag & USER_TOOLTIPS_PYTHON) == 0) { | if ((U.flag & USER_TOOLTIPS_PYTHON) == 0) { | ||||
| BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Python: %s"), str); | BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Python: %s"), str); | ||||
| data->flag[data->totline] |= UI_TIP_ROW_PADDING; | |||||
| data->color_id[data->totline] = UI_TIP_LC_PYTHON; | data->color_id[data->totline] = UI_TIP_LC_PYTHON; | ||||
| data->totline++; | data->totline++; | ||||
| } | } | ||||
| Context not available. | |||||
| BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), | BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), | ||||
| TIP_("Python: %s"), rna_struct.strinfo); | TIP_("Python: %s"), rna_struct.strinfo); | ||||
| } | } | ||||
| data->flag[data->totline] |= UI_TIP_ROW_PADDING; | |||||
| data->color_id[data->totline] = UI_TIP_LC_PYTHON; | data->color_id[data->totline] = UI_TIP_LC_PYTHON; | ||||
| data->totline++; | data->totline++; | ||||
| Context not available. | |||||
| /* set font, get bb */ | /* set font, get bb */ | ||||
| data->fstyle = style->widget; /* copy struct */ | data->fstyle = style->widget; /* copy struct */ | ||||
| data->fstyle.align = UI_STYLE_TEXT_CENTER; | |||||
| ui_fontscale(&data->fstyle.points, aspect); | ui_fontscale(&data->fstyle.points, aspect); | ||||
| uiStyleFontSet(&data->fstyle); | uiStyleFontSet(&data->fstyle); | ||||
| /* these defines tweaked depending on font */ | for (a = 0, fontw = 0, fonth = 0; a < data->totline; a++) { | ||||
| #define TIP_MARGIN_Y (2.0f / aspect) | if (data->flag[a] & UI_TIP_HEADER) { | ||||
| #define TIP_BORDER_X (16.0f / aspect) | // BLF_size(data->fstyle.uifont_id, 12 * U.pixelsize, U.dpi); | ||||
| #define TIP_BORDER_Y (6.0f / aspect) | |||||
| h = BLF_height_max(data->fstyle.uifont_id); | if (enum_label.strinfo) | ||||
| w = BLF_width(data->fstyle.uifont_id, data->header, sizeof(data->header)) + | |||||
| BLF_width(data->fstyle.uifont_id, data->active_info, sizeof(data->active_info)); | |||||
| else | |||||
| w = BLF_width(data->fstyle.uifont_id, data->header, sizeof(data->header)); | |||||
| h = BLF_height_max(data->fstyle.uifont_id); | |||||
| } | |||||
| else { | |||||
| // BLF_size(data->fstyle.uifont_id, 11 * U.pixelsize, U.dpi); | |||||
| w = BLF_width(data->fstyle.uifont_id, data->lines[a], sizeof(data->lines[a])); | |||||
| h = BLF_height_max(data->fstyle.uifont_id); | |||||
| } | |||||
| for (a = 0, fontw = 0, fonth = 0; a < data->totline; a++) { | |||||
| w = BLF_width(data->fstyle.uifont_id, data->lines[a], sizeof(data->lines[a])); | |||||
| fontw = max_ff(fontw, (float)w); | fontw = max_ff(fontw, (float)w); | ||||
| fonth += (a == 0) ? h : h + TIP_MARGIN_Y; | |||||
| if (data->flag[a + 1] & UI_TIP_ROW_PADDING) | |||||
| fonth += h * 1.3f; | |||||
| else | |||||
| fonth += h; | |||||
| } | } | ||||
| //fontw *= aspect; | //fontw *= aspect; | ||||
| Context not available. | |||||
| ar->regiondata = data; | ar->regiondata = data; | ||||
| data->toth = fonth; | data->toth = fonth; | ||||
| data->linew = fontw; | |||||
| data->lineh = h; | data->lineh = h; | ||||
| data->spaceh = TIP_MARGIN_Y; | |||||
| /* compute position */ | rect_fl.xmin = TOOLTIP_PADDING * 0.9f; | ||||
| ofsx = 0; //(but->block->panel) ? but->block->panel->ofsx : 0; | rect_fl.xmax = rect_fl.xmin + fontw + TOOLTIP_PADDING; | ||||
| ofsy = 0; //(but->block->panel) ? but->block->panel->ofsy : 0; | rect_fl.ymax = -TOOLTIP_PADDING * 0.7f; | ||||
| rect_fl.ymin = rect_fl.ymax - fonth; | |||||
| rect_fl.xmin = BLI_rctf_cent_x(&but->rect) + ofsx - TIP_BORDER_X; | |||||
| rect_fl.xmax = rect_fl.xmin + fontw + (TIP_BORDER_X * 2); | |||||
| rect_fl.ymax = but->rect.ymin + ofsy - TIP_BORDER_Y; | |||||
| rect_fl.ymin = rect_fl.ymax - fonth - TIP_BORDER_Y; | |||||
| #undef TIP_MARGIN_Y | |||||
| #undef TIP_BORDER_X | |||||
| #undef TIP_BORDER_Y | |||||
| /* since the text has beens caled already, the size of tooltips is defined now */ | /* since the text has beens caled already, the size of tooltips is defined now */ | ||||
| /* here we try to figure out the right location */ | /* here we try to figure out the right location */ | ||||
| if (butregion) { | if (butregion) { | ||||
| int mx, my; | |||||
| float ofsx_fl = rect_fl.xmin, ofsy_fl = rect_fl.ymax; | float ofsx_fl = rect_fl.xmin, ofsy_fl = rect_fl.ymax; | ||||
| wm_get_cursor_position(win, &mx, &my); | |||||
| ui_block_to_window_fl(butregion, but->block, &ofsx_fl, &ofsy_fl); | ui_block_to_window_fl(butregion, but->block, &ofsx_fl, &ofsy_fl); | ||||
| BLI_rctf_translate(&rect_fl, ofsx_fl - rect_fl.xmin, ofsy_fl - rect_fl.ymax); | BLI_rctf_translate(&rect_fl, mx, my); | ||||
| } | } | ||||
| BLI_rcti_rctf_copy(&rect_i, &rect_fl); | BLI_rcti_rctf_copy(&rect_i, &rect_fl); | ||||
| Context not available. | |||||
| rect_i.ymin = 30; | rect_i.ymin = 30; | ||||
| } | } | ||||
| /* add padding */ | |||||
| BLI_rcti_resize(&rect_i, BLI_rcti_size_x(&rect_i) + TOOLTIP_PADDING, BLI_rcti_size_y(&rect_i) + TOOLTIP_PADDING); | |||||
| /* widget rect, in region coords */ | /* widget rect, in region coords */ | ||||
| { | { | ||||
| int width = UI_ThemeMenuShadowWidth(); | int width = UI_ThemeMenuShadowWidth(); | ||||
| data->bbox.xmin = width; | data->bbox.xmin = width; | ||||
| data->bbox.xmax = BLI_rcti_size_x(&rect_i) + width; | data->bbox.xmax = BLI_rcti_size_x(&rect_i) - width; | ||||
| data->bbox.ymin = width; | data->bbox.ymin = width; | ||||
| data->bbox.ymax = BLI_rcti_size_y(&rect_i) + width; | data->bbox.ymax = BLI_rcti_size_y(&rect_i); | ||||
| /* region bigger for shadow */ | /* region bigger for shadow */ | ||||
| ar->winrct.xmin = rect_i.xmin - width; | ar->winrct.xmin = rect_i.xmin - width; | ||||
| ar->winrct.xmax = rect_i.xmax + width; | ar->winrct.xmax = rect_i.xmax + width; | ||||
| ar->winrct.ymin = rect_i.ymin - width; | ar->winrct.ymin = rect_i.ymin - width; | ||||
| ar->winrct.ymax = rect_i.ymax + MENU_TOP; | ar->winrct.ymax = rect_i.ymax + width; | ||||
| } | } | ||||
| /* adds subwindow */ | /* adds subwindow */ | ||||
| Context not available. | |||||
Name SUBMENU isnt very helpful/informative.