diff options
Diffstat (limited to 'source/blender/editors/interface')
18 files changed, 1973 insertions, 921 deletions
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index bad09a7c441..e045db8fdd2 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -37,6 +37,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_userdef_types.h" @@ -82,11 +83,11 @@ #define B_NOP -1 -/* - * a full doc with API notes can be found in bf-blender/trunk/blender/doc/guides/interface_API.txt +/** + * a full doc with API notes can be found in 'blender/doc/guides/interface_API.txt' * - * uiBlahBlah() external function - * ui_blah_blah() internal function + * `uiBlahBlah()` external function. + * `ui_blah_blah()` internal function. */ static void ui_but_free(const bContext *C, uiBut *but); @@ -513,7 +514,7 @@ static void ui_draw_links(uiBlock *block) uiBut *but; uiLinkLine *line; - /* Draw the grey out lines. Do this first so they appear at the + /* 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; @@ -548,7 +549,7 @@ static void ui_draw_links(uiBlock *block) } /* Draw any active lines (lines with either button being hovered over). - * Do this last so they appear on top of inactive and grey out lines. */ + * 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) { @@ -1099,13 +1100,16 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but, return found; } -/* this goes in a seemingly weird pattern: +/** + * This goes in a seemingly weird pattern: * + * <pre> * 4 * 5 6 * 1 2 * 7 8 * 3 + * </pre> * * but it's actually quite logical. It's designed to be 'upwards compatible' * for muscle memory so that the menu item locations are fixed and don't move @@ -1930,7 +1934,7 @@ void ui_but_value_set(uiBut *but, double value) int ui_but_string_get_max_length(uiBut *but) { - if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) + if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) return but->hardmax; else return UI_MAX_DRAW_STR; @@ -1951,6 +1955,56 @@ uiBut *ui_but_drag_multi_edit_get(uiBut *but) return but_iter; } +/** \name Check to show extra icons + * + * Extra icons are shown on the right hand side of buttons. + * \{ */ + +static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but) +{ + BLI_assert(but->type == UI_BTYPE_SEARCH_MENU); + return ((but->editstr == NULL) && + (but->drawstr[0] != '\0') && + (but->flag & UI_BUT_SEARCH_UNLINK)); +} + +static bool ui_but_icon_extra_is_visible_eyedropper(uiBut *but) +{ + StructRNA *type; + short idcode; + + BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_SEARCH_UNLINK)); + + if (but->rnaprop == NULL) { + return false; + } + + type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop); + idcode = RNA_type_to_ID_code(type); + + + return ((but->editstr == NULL) && + (idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode))); +} + +uiButExtraIconType ui_but_icon_extra_get(uiBut *but) +{ + if ((but->flag & UI_BUT_SEARCH_UNLINK) == 0) { + /* pass */ + } + else if (ui_but_icon_extra_is_visible_search_unlink(but)) { + return UI_BUT_ICONEXTRA_UNLINK; + } + else if (ui_but_icon_extra_is_visible_eyedropper(but)) { + return UI_BUT_ICONEXTRA_EYEDROPPER; + } + + return UI_BUT_ICONEXTRA_NONE; +} + +/** \} */ + + static double ui_get_but_scale_unit(uiBut *but, double value) { UnitSettings *unit = but->block->unit; @@ -2031,7 +2085,7 @@ static float ui_get_but_step_unit(uiBut *but, float step_default) */ void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision) { - if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { PropertyType type; const char *buf = NULL; int buf_len; @@ -2073,7 +2127,7 @@ void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int BLI_strncpy(str, but->poin, maxlen); return; } - else if (ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + else if (but->type == UI_BTYPE_SEARCH_MENU) { /* string */ BLI_strncpy(str, but->poin, maxlen); return; @@ -2194,7 +2248,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, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { if (RNA_property_editable(&but->rnapoin, but->rnaprop)) { PropertyType type; @@ -2246,7 +2300,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) return true; } - else if (ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + else if (but->type == UI_BTYPE_SEARCH_MENU) { /* string */ BLI_strncpy(but->poin, str, but->hardmax); return true; @@ -2264,6 +2318,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) double value; if (ui_but_string_set_eval_num(C, but, str, &value) == false) { + WM_report_banner_show(C); return false; } @@ -2714,11 +2769,11 @@ void ui_but_update(uiBut *but) } else { const int prec = ui_but_calc_float_precision(but, value); - slen += BLI_snprintf(but->drawstr + slen, sizeof(but->drawstr) - slen, "%.*f", prec, value); + slen += BLI_snprintf_rlen(but->drawstr + slen, sizeof(but->drawstr) - slen, "%.*f", prec, value); } } else { - slen += BLI_snprintf(but->drawstr + slen, sizeof(but->drawstr) - slen, "%d", (int)value); + slen += BLI_snprintf_rlen(but->drawstr + slen, sizeof(but->drawstr) - slen, "%d", (int)value); } if (but->rnaprop) { @@ -2754,7 +2809,6 @@ void ui_but_update(uiBut *but) case UI_BTYPE_TEXT: case UI_BTYPE_SEARCH_MENU: - case UI_BTYPE_SEARCH_MENU_UNLINK: if (!but->editstr) { char str[UI_MAX_DRAW_STR]; @@ -3047,17 +3101,18 @@ void ui_block_cm_to_scene_linear_v3(uiBlock *block, float pixel[3]) /** * \brief ui_def_but is the function that draws many button types * - * \param x,y The lower left hand corner of the button (X axis) - * \param width,height The size of the button. + * \param x, y: The lower left hand corner of the button (X axis) + * \param width, height: The size of the button. * * for float buttons: - * - \a a1 Click Step (how much to change the value each click) - * - \a a2 Number of decimal point values to display. 0 defaults to 3 (0.000) - * 1,2,3, and a maximum of 4, all greater values will be clamped to 4. + * \param a1: Click Step (how much to change the value each click) + * \param a2: Number of decimal point values to display. 0 defaults to 3 (0.000) + * 1,2,3, and a maximum of 4, all greater values will be clamped to 4. */ -static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, - int x, int y, short width, short height, - void *poin, float min, float max, float a1, float a2, const char *tip) +static uiBut *ui_def_but( + uiBlock *block, int type, int retval, const char *str, + int x, int y, short width, short height, + void *poin, float min, float max, float a1, float a2, const char *tip) { uiBut *but; int slen; @@ -3139,7 +3194,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, 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_SEARCH_MENU_UNLINK)) + UI_BTYPE_PROGRESS_BAR)) { but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT); } @@ -3186,6 +3241,19 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, return but; } +void ui_def_but_icon(uiBut *but, const int icon, const int flag) +{ + if (icon) { + ui_icon_ensure_deferred(but->block->evil_C, icon, (flag & UI_BUT_ICON_PREVIEW) != 0); + } + but->icon = (BIFIconID)icon; + but->flag |= flag; + + if (but->str && but->str[0]) { + but->drawflag |= UI_BUT_ICON_LEFT; + } +} + static void ui_def_but_rna__disable(uiBut *but) { but->flag |= UI_BUT_DISABLED; @@ -3325,10 +3393,11 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu * When this kind of change won't disrupt branches, best look into making more * of our UI functions take prop rather then propname. */ -static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *str, - int x, int y, short width, short height, - PointerRNA *ptr, PropertyRNA *prop, int index, - float min, float max, float a1, float a2, const char *tip) +static uiBut *ui_def_but_rna( + uiBlock *block, int type, int retval, const char *str, + int x, int y, short width, short height, + PointerRNA *ptr, PropertyRNA *prop, int index, + float min, float max, float a1, float a2, const char *tip) { const PropertyType proptype = RNA_property_type(prop); uiBut *but; @@ -3448,11 +3517,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s but->rnaindex = 0; if (icon) { - but->icon = (BIFIconID)icon; - but->flag |= UI_HAS_ICON; - if (str[0]) { - but->drawflag |= UI_BUT_ICON_LEFT; - } + ui_def_but_icon(but, icon, UI_HAS_ICON); } if ((type == UI_BTYPE_MENU) && (but->dt == UI_EMBOSS_PULLDOWN)) { @@ -3639,8 +3704,7 @@ int UI_autocomplete_end(AutoComplete *autocpl, char *autoname) static void ui_but_update_and_icon_set(uiBut *but, int icon) { if (icon) { - but->icon = (BIFIconID) icon; - but->flag |= UI_HAS_ICON; + ui_def_but_icon(but, icon, UI_HAS_ICON); } ui_but_update(but); @@ -4014,7 +4078,7 @@ void UI_but_drag_set_value(uiBut *but) void UI_but_drag_set_image(uiBut *but, const char *path, int icon, struct ImBuf *imb, float scale) { but->dragtype = WM_DRAG_PATH; - but->icon = icon; /* no flag UI_HAS_ICON, so icon doesnt draw in button */ + ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesnt draw in button */ but->dragpoin = (void *)path; but->imb = imb; but->imb_scale = scale; @@ -4168,8 +4232,7 @@ uiBut *uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, in { uiBut *but = ui_def_but(block, UI_BTYPE_PULLDOWN, 0, str, x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip); - but->icon = (BIFIconID) icon; - but->flag |= UI_HAS_ICON; + ui_def_but_icon(but, icon, UI_HAS_ICON); but->drawflag |= UI_BUT_ICON_LEFT; but->flag |= UI_BUT_ICON_SUBMENU; @@ -4184,8 +4247,7 @@ uiBut *uiDefIconMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int ic { uiBut *but = ui_def_but(block, UI_BTYPE_PULLDOWN, 0, "", x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip); - but->icon = (BIFIconID) icon; - but->flag |= UI_HAS_ICON; + ui_def_but_icon(but, icon, UI_HAS_ICON); but->drawflag &= ~UI_BUT_ICON_LEFT; but->menu_create_func = func; @@ -4201,7 +4263,7 @@ uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, /* XXX temp, old menu calls pass on icon arrow, which is now UI_BUT_ICON_SUBMENU flag */ if (icon != ICON_RIGHTARROW_THIN) { - but->icon = (BIFIconID) icon; + ui_def_but_icon(but, icon, 0); but->drawflag |= UI_BUT_ICON_LEFT; } but->flag |= UI_HAS_ICON; @@ -4218,9 +4280,8 @@ uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int { uiBut *but = ui_def_but(block, UI_BTYPE_BLOCK, retval, "", x, y, width, height, arg, 0.0, 0.0, 0.0, 0.0, tip); - but->icon = (BIFIconID) icon; - but->flag |= UI_HAS_ICON; - + ui_def_but_icon(but, icon, UI_HAS_ICON); + but->drawflag |= UI_BUT_ICON_LEFT; but->block_create_func = func; @@ -4253,9 +4314,8 @@ uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxle { uiBut *but = ui_def_but(block, UI_BTYPE_SEARCH_MENU, retval, "", x, y, width, height, arg, 0.0, maxlen, a1, a2, tip); - but->icon = (BIFIconID) icon; - but->flag |= UI_HAS_ICON; - + ui_def_but_icon(but, icon, UI_HAS_ICON); + but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT; ui_but_update(but); @@ -4264,8 +4324,11 @@ uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxle } -/* arg is user value, searchfunc and handlefunc both get it as arg */ -/* if active set, button opens with this item visible and selected */ +/** + * \param sfunc, bfunc: both get it as \a arg. + * \param arg: user value, + * \param active: when set, button opens with this item visible and selected. + */ void UI_but_func_search_set(uiBut *but, uiButSearchFunc sfunc, void *arg, uiButHandleFunc bfunc, void *active) { but->search_func = sfunc; @@ -4334,11 +4397,14 @@ static void operator_enum_call_cb(struct bContext *UNUSED(C), void *but, void *a } } -/* Same parameters as for uiDefSearchBut, with additional operator type and properties, used by callback - * to call again the right op with the right options (properties values). */ -uiBut *uiDefSearchButO_ptr(uiBlock *block, wmOperatorType *ot, IDProperty *properties, - void *arg, int retval, int icon, int maxlen, int x, int y, - short width, short height, float a1, float a2, const char *tip) +/** + * Same parameters as for uiDefSearchBut, with additional operator type and properties, used by callback + * to call again the right op with the right options (properties values). + */ +uiBut *uiDefSearchButO_ptr( + uiBlock *block, wmOperatorType *ot, IDProperty *properties, + void *arg, int retval, int icon, int maxlen, int x, int y, + short width, short height, float a1, float a2, const char *tip) { uiBut *but; @@ -4357,7 +4423,8 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block, wmOperatorType *ot, IDProperty *prope return but; } -/* push a new event onto event queue to activate the given button +/** + * push a new event onto event queue to activate the given button * (usually a text-field) upon entering a popup */ void UI_but_focus_on_enter_event(wmWindow *win, uiBut *but) @@ -4390,7 +4457,19 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) if (type == BUT_GET_LABEL) { if (but->str) { - tmp = BLI_strdup(but->str); + const char *str_sep; + size_t str_len; + + if ((but->flag & UI_BUT_HAS_SEP_CHAR) && + (str_sep = strrchr(but->str, UI_SEP_CHAR))) + { + str_len = (str_sep - but->str); + } + else { + str_len = strlen(but->str); + } + + tmp = BLI_strdupn(but->str, str_len); } else { type = BUT_GET_RNA_LABEL; /* Fail-safe solution... */ diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 24a30ebe3d8..f6757b35462 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -54,13 +54,13 @@ #include "interface_intern.h" -static FCurve *ui_but_get_fcurve(uiBut *but, AnimData **adt, bAction **action, bool *r_driven) +static FCurve *ui_but_get_fcurve(uiBut *but, AnimData **adt, bAction **action, bool *r_driven, bool *r_special) { /* for entire array buttons we check the first component, it's not perfect * but works well enough in typical cases */ int rnaindex = (but->rnaindex == -1) ? 0 : but->rnaindex; - return rna_get_fcurve_context_ui(but->block->evil_C, &but->rnapoin, but->rnaprop, rnaindex, adt, action, r_driven); + return rna_get_fcurve_context_ui(but->block->evil_C, &but->rnapoin, but->rnaprop, rnaindex, adt, action, r_driven, r_special); } void ui_but_anim_flag(uiBut *but, float cfra) @@ -69,11 +69,16 @@ void ui_but_anim_flag(uiBut *but, float cfra) bAction *act; FCurve *fcu; bool driven; - + bool special; + but->flag &= ~(UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN); - - fcu = ui_but_get_fcurve(but, &adt, &act, &driven); - + + /* NOTE: "special" is reserved for special F-Curves stored on the animation data + * itself (which are used to animate properties of the animation data). + * We count those as "animated" too for now + */ + fcu = ui_but_get_fcurve(but, &adt, &act, &driven, &special); + if (fcu) { if (!driven) { but->flag |= UI_BUT_ANIMATED; @@ -98,10 +103,10 @@ bool ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen) { FCurve *fcu; ChannelDriver *driver; - bool driven; - - fcu = ui_but_get_fcurve(but, NULL, NULL, &driven); - + bool driven, special; + + fcu = ui_but_get_fcurve(but, NULL, NULL, &driven, &special); + if (fcu && driven) { driver = fcu->driver; @@ -118,9 +123,9 @@ bool ui_but_anim_expression_set(uiBut *but, const char *str) { FCurve *fcu; ChannelDriver *driver; - bool driven; + bool driven, special; - fcu = ui_but_get_fcurve(but, NULL, NULL, &driven); + fcu = ui_but_get_fcurve(but, NULL, NULL, &driven, &special); if (fcu && driven) { driver = fcu->driver; @@ -215,8 +220,9 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra) bAction *action; FCurve *fcu; bool driven; + bool special; - fcu = ui_but_get_fcurve(but, NULL, &action, &driven); + fcu = ui_but_get_fcurve(but, NULL, &action, &driven, &special); if (fcu && !driven) { id = but->rnapoin.id.data; diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 07d580b9138..2c13b199bba 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -508,8 +508,9 @@ static void draw_scope_end(const rctf *rect, GLint *scissor) UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f); } -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) +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) { int i; @@ -1260,8 +1261,8 @@ void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect) size = BLI_rcti_size_x(rect) / 200.f; else size = BLI_rcti_size_y(rect) / 200.f; - - glScalef(size, size, size); + + glScalef(size, size, MIN2(size, 1.0f)); if (displist == 0) { GLUquadricObj *qobj; @@ -1453,7 +1454,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti glEnd(); } else if (cumap->cur == 3) { - float lum = rgb_to_bw(cumap->sample); + float lum = IMB_colormanagement_get_luminance(cumap->sample); glColor3ub(240, 240, 240); glBegin(GL_LINES); diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index aabb8e29fa9..97aa865c287 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -36,6 +36,8 @@ #include "BLI_blenlib.h" #include "BLI_math_vector.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_screen.h" #include "BKE_report.h" @@ -176,8 +178,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int if (sa) { if (sa->spacetype == SPACE_IMAGE) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { SpaceImage *sima = sa->spacedata.first; int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; @@ -188,8 +190,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int } } else if (sa->spacetype == SPACE_NODE) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { SpaceNode *snode = sa->spacedata.first; int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; @@ -200,8 +202,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int } } else if (sa->spacetype == SPACE_CLIP) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { SpaceClip *sc = sa->spacedata.first; int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; @@ -379,12 +381,11 @@ void UI_OT_eyedropper_color(wmOperatorType *ot) /* -------------------------------------------------------------------- */ -/* Data Dropper - * - * note: datadropper is only internal name to avoid confusion in this file - */ +/* Data Dropper */ /** \name Eyedropper (ID data-blocks) + * + * \note: datadropper is only internal name to avoid confusion in this file. * \{ */ typedef struct DataDropper { @@ -436,7 +437,8 @@ static int datadropper_init(bContext *C, wmOperator *op) type = RNA_property_pointer_type(&ddr->ptr, ddr->prop); ddr->idcode = RNA_type_to_ID_code(type); BLI_assert(ddr->idcode != 0); - ddr->idcode_name = BKE_idcode_to_name(ddr->idcode); + /* Note we can translate here (instead of on draw time), because this struct has very short lifetime. */ + ddr->idcode_name = TIP_(BKE_idcode_to_name(ddr->idcode)); return true; } @@ -456,6 +458,8 @@ static void datadropper_exit(bContext *C, wmOperator *op) op->customdata = NULL; } + + WM_event_add_mousemove(C); } static void datadropper_cancel(bContext *C, wmOperator *op) @@ -482,8 +486,8 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int if (sa) { if (sa->spacetype == SPACE_VIEW3D) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { const int mval[2] = { mx - ar->winrct.xmin, my - ar->winrct.ymin}; @@ -632,7 +636,7 @@ void UI_OT_eyedropper_id(wmOperatorType *ot) /* identifiers */ ot->name = "Eyedropper Datablock"; ot->idname = "UI_OT_eyedropper_id"; - ot->description = "Sample a color from the Blender Window to store in a property"; + ot->description = "Sample a datablock from the Blender Window to store in a property"; /* api callbacks */ ot->invoke = datadropper_invoke; @@ -651,12 +655,11 @@ void UI_OT_eyedropper_id(wmOperatorType *ot) /* -------------------------------------------------------------------- */ -/* Depth Dropper - * - * note: depthdropper is only internal name to avoid confusion in this file - */ +/* Depth Dropper */ /** \name Eyedropper (Depth) + * + * \note: depthdropper is only internal name to avoid confusion in this file. * \{ */ typedef struct DepthDropper { @@ -765,8 +768,8 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, if (sa) { if (sa->spacetype == SPACE_VIEW3D) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; /* weak, we could pass in some reference point */ diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index a6ff5bb3ad3..58cf6b900b9 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -52,9 +52,9 @@ #include "BLI_linklist.h" #include "BLI_string.h" #include "BLI_string_utf8.h" +#include "BLI_string_cursor_utf8.h" #include "BLI_rect.h" #include "BLI_utildefines.h" -#include "BLI_string_cursor_utf8.h" #include "BLF_translation.h" @@ -99,6 +99,9 @@ /* support dragging multiple number buttons at once */ #define USE_DRAG_MULTINUM +/* allow dragging/editing all other selected items at once */ +#define USE_ALLSELECT + /* so we can avoid very small mouse-moves from jumping away from keyboard navigation [#34936] */ #define USE_KEYNAV_LIMIT @@ -158,17 +161,63 @@ typedef enum uiHandleButtonState { } uiHandleButtonState; +#ifdef USE_ALLSELECT + +/* Unfortunately theres no good way handle more generally: + * (propagate single clicks on layer buttons to other objects) */ +#define USE_ALLSELECT_LAYER_HACK + +typedef struct uiSelectContextElem { + PointerRNA ptr; + union { + bool val_b; + int val_i; + float val_f; + }; +} uiSelectContextElem; + +typedef struct uiSelectContextStore { + uiSelectContextElem *elems; + int elems_len; + bool do_free; + bool is_enabled; + /* When set, simply copy values (don't apply difference). + * Rules are: + * - dragging numbers uses delta. + * - typing in values will assign to all. */ + bool is_copy; +} uiSelectContextStore; + +static bool ui_selectcontext_begin( + bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data); +static void ui_selectcontext_end( + uiBut *but, uiSelectContextStore *selctx_data); +static void ui_selectcontext_apply( + bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data, + const double value, const double value_orig); + +#define IS_ALLSELECT_EVENT(event) ((event)->alt != 0) + +/** just show a tinted color so users know its activated */ +#define UI_BUT_IS_SELECT_CONTEXT UI_BUT_NODE_ACTIVE + +#endif /* USE_ALLSELECT */ + + #ifdef USE_DRAG_MULTINUM -/* how far to drag before we check for gesture direction (in pixels), +/** + * how far to drag before we check for gesture direction (in pixels), * note: half the height of a button is about right... */ #define DRAG_MULTINUM_THRESHOLD_DRAG_X (UI_UNIT_Y / 4) -/* how far to drag horizontally before we stop checking which buttons the gesture spans (in pixels), +/** + * how far to drag horizontally before we stop checking which buttons the gesture spans (in pixels), * locking down the buttons so we can drag freely without worrying about vertical movement. */ #define DRAG_MULTINUM_THRESHOLD_DRAG_Y (UI_UNIT_Y / 4) -/* how strict to be when detecting a vertical gesture, [0.5 == sloppy], [0.9 == strict], (unsigned dot-product) +/** + * how strict to be when detecting a vertical gesture, [0.5 == sloppy], [0.9 == strict], (unsigned dot-product) * note: we should be quite strict here, since doing a vertical gesture by accident should be avoided, * however with some care a user should be able to do a vertical movement without *missing*. */ #define DRAG_MULTINUM_THRESHOLD_VERTICAL (0.75f) @@ -178,6 +227,10 @@ typedef enum uiHandleButtonState { typedef struct uiButMultiState { double origvalue; uiBut *but; + +#ifdef USE_ALLSELECT + uiSelectContextStore select_others; +#endif } uiButMultiState; typedef struct uiHandleButtonMulti { @@ -210,8 +263,6 @@ typedef struct uiHandleButtonMulti { #endif /* USE_DRAG_MULTINUM */ - - typedef struct uiHandleButtonData { wmWindowManager *wm; wmWindow *window; @@ -280,6 +331,10 @@ typedef struct uiHandleButtonData { uiHandleButtonMulti multi_data; #endif +#ifdef USE_ALLSELECT + uiSelectContextStore select_others; +#endif + /* post activate */ uiButtonActivateType posttype; uiBut *postbut; @@ -328,14 +383,14 @@ static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, c static uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event); static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type); static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state); -static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *data, - const bool mousemove, const bool onfree); +static void button_activate_exit( + bContext *C, uiBut *but, uiHandleButtonData *data, + const bool mousemove, const bool onfree); static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *userdata); static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type); -static void button_timers_tooltip_remove(bContext *C, uiBut *but); #ifdef USE_DRAG_MULTINUM -static void ui_multibut_restore(uiHandleButtonData *data, uiBlock *block); +static void ui_multibut_restore(bContext *C, uiHandleButtonData *data, uiBlock *block); static uiButMultiState *ui_multibut_lookup(uiHandleButtonData *data, const uiBut *but); #endif @@ -366,7 +421,7 @@ static void ui_color_snap_hue(const enum eSnapType snap, float *r_hue) { const float snap_increment = (snap == SNAP_ON_SMALL) ? 24 : 12; BLI_assert(snap != SNAP_OFF); - *r_hue = floorf(0.5f + ((*r_hue) * snap_increment)) / snap_increment; + *r_hue = roundf((*r_hue) * snap_increment) / snap_increment; } /* assumes event type is MOUSEPAN */ @@ -413,7 +468,7 @@ bool ui_but_is_editable_as_text(const uiBut *but) { return ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, - UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK); + UI_BTYPE_SEARCH_MENU); } @@ -478,10 +533,9 @@ static float ui_mouse_scale_warp_factor(const bool shift) return shift ? 0.05f : 1.0f; } -static void ui_mouse_scale_warp(uiHandleButtonData *data, - const float mx, const float my, - float *r_mx, float *r_my, - const bool shift) +static void ui_mouse_scale_warp( + uiHandleButtonData *data, const float mx, const float my, + float *r_mx, float *r_my, const bool shift) { const float fac = ui_mouse_scale_warp_factor(shift); @@ -894,7 +948,7 @@ static uiButMultiState *ui_multibut_lookup(uiHandleButtonData *data, const uiBut return NULL; } -static void ui_multibut_restore(uiHandleButtonData *data, uiBlock *block) +static void ui_multibut_restore(bContext *C, uiHandleButtonData *data, uiBlock *block) { uiBut *but; @@ -903,6 +957,16 @@ static void ui_multibut_restore(uiHandleButtonData *data, uiBlock *block) uiButMultiState *mbut_state = ui_multibut_lookup(data, but); if (mbut_state) { ui_but_value_set(but, mbut_state->origvalue); + +#ifdef USE_ALLSELECT + if (mbut_state->select_others.elems_len > 0) { + ui_selectcontext_apply( + C, but, &mbut_state->select_others, + mbut_state->origvalue, mbut_state->origvalue); + } +#else + UNUSED_VARS(C); +#endif } } } @@ -910,7 +974,26 @@ static void ui_multibut_restore(uiHandleButtonData *data, uiBlock *block) static void ui_multibut_free(uiHandleButtonData *data, uiBlock *block) { +#ifdef USE_ALLSELECT + if (data->multi_data.mbuts) { + LinkNode *list = data->multi_data.mbuts; + while (list) { + LinkNode *next = list->next; + uiButMultiState *mbut_state = list->link; + + if (mbut_state->select_others.elems) { + MEM_freeN(mbut_state->select_others.elems); + } + + MEM_freeN(list->link); + MEM_freeN(list); + list = next; + } + } +#else BLI_linklist_freeN(data->multi_data.mbuts); +#endif + data->multi_data.mbuts = NULL; if (data->multi_data.bs_mbuts) { @@ -979,6 +1062,7 @@ static void ui_multibut_states_create(uiBut *but_active, uiHandleButtonData *dat uiBut *but; BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_SETUP); + BLI_assert(data->multi_data.has_mbuts); data->multi_data.bs_mbuts = UI_butstore_create(but_active->block); @@ -1016,6 +1100,24 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl void *active_back; ui_but_execute_begin(C, ar, but, &active_back); + +#ifdef USE_ALLSELECT + if (data->select_others.is_enabled) { + /* init once! */ + if (mbut_state->select_others.elems_len == 0) { + ui_selectcontext_begin(C, but, &mbut_state->select_others); + } + if (mbut_state->select_others.elems_len == 0) { + mbut_state->select_others.elems_len = -1; + } + } + + /* needed so we apply the right deltas */ + but->active->origvalue = mbut_state->origvalue; + but->active->select_others = mbut_state->select_others; + but->active->select_others.do_free = false; +#endif + BLI_assert(active_back == NULL); /* no need to check 'data->state' here */ if (data->str) { @@ -1064,8 +1166,9 @@ typedef struct uiDragToggleHandle { int xy_last[2]; } uiDragToggleHandle; -static bool ui_drag_toggle_set_xy_xy(bContext *C, ARegion *ar, const bool is_set, const eButType but_type_start, - const int xy_src[2], const int xy_dst[2]) +static bool ui_drag_toggle_set_xy_xy( + bContext *C, ARegion *ar, const bool is_set, const eButType but_type_start, + const int xy_src[2], const int xy_dst[2]) { /* popups such as layers won't re-evaluate on redraw */ const bool do_check = (ar->regiontype == RGN_TYPE_TEMPORARY); @@ -1225,6 +1328,267 @@ static bool ui_but_is_drag_toggle(const uiBut *but) #endif /* USE_DRAG_TOGGLE */ +#ifdef USE_ALLSELECT + +static bool ui_selectcontext_begin( + bContext *C, uiBut *but, uiSelectContextStore *selctx_data) +{ + PointerRNA ptr, lptr, idptr; + PropertyRNA *prop, *lprop; + bool success = false; + int index; + + char *path = NULL; + ListBase lb = {NULL}; + + ptr = but->rnapoin; + prop = but->rnaprop; + index = but->rnaindex; + + /* for now don't support whole colors */ + if (index == -1) + return false; + + /* if there is a valid property that is editable... */ + if (ptr.data && prop) { + CollectionPointerLink *link; + bool use_path_from_id; + int i; + + /* some facts we want to know */ + const bool is_array = RNA_property_array_check(prop); + const int rna_type = RNA_property_type(prop); + + if (!UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path)) { + goto finally; + } + + selctx_data->elems_len = BLI_listbase_count(&lb); + if (selctx_data->elems_len == 0) { + goto finally; + } + + selctx_data->elems = MEM_mallocN(sizeof(uiSelectContextElem) * selctx_data->elems_len, __func__); + + for (i = 0, link = lb.first; i < selctx_data->elems_len; i++, link = link->next) { + uiSelectContextElem *other = &selctx_data->elems[i]; + /* TODO,. de-duplicate copy_to_selected_button */ + if (link->ptr.data != ptr.data) { + if (use_path_from_id) { + /* Path relative to ID. */ + lprop = NULL; + RNA_id_pointer_create(link->ptr.id.data, &idptr); + RNA_path_resolve_property(&idptr, path, &lptr, &lprop); + } + else if (path) { + /* Path relative to elements from list. */ + lprop = NULL; + RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop); + } + else { + lptr = link->ptr; + lprop = prop; + } + + /* lptr might not be the same as link->ptr! */ + if ((lptr.data != ptr.data) && + (lprop == prop) && + RNA_property_editable(&lptr, lprop)) + { + other->ptr = lptr; + if (is_array) { + if (rna_type == PROP_FLOAT) { + other->val_f = RNA_property_float_get_index(&lptr, lprop, index); + } + else if (rna_type == PROP_INT) { + other->val_i = RNA_property_int_get_index(&lptr, lprop, index); + } + /* ignored for now */ +#if 0 + else if (rna_type == PROP_BOOLEAN) { + other->val_b = RNA_property_boolean_get_index(&lptr, lprop, index); + } +#endif + } + else { + if (rna_type == PROP_FLOAT) { + other->val_f = RNA_property_float_get(&lptr, lprop); + } + else if (rna_type == PROP_INT) { + other->val_i = RNA_property_int_get(&lptr, lprop); + } + /* ignored for now */ +#if 0 + else if (rna_type == PROP_BOOLEAN) { + other->val_b = RNA_property_boolean_get(&lptr, lprop); + } + else if (rna_type == PROP_ENUM) { + other->val_i = RNA_property_enum_get(&lptr, lprop); + } +#endif + } + + continue; + } + } + + selctx_data->elems_len -= 1; + i -= 1; + } + } + + success = (selctx_data->elems_len != 0); + +finally: + if (selctx_data->elems_len == 0) { + MEM_SAFE_FREE(selctx_data->elems); + } + + MEM_SAFE_FREE(path); + BLI_freelistN(&lb); + + /* caller can clear */ + selctx_data->do_free = true; + + if (success) { + but->flag |= UI_BUT_IS_SELECT_CONTEXT; + } + + return success; +} + +static void ui_selectcontext_end( + uiBut *but, uiSelectContextStore *selctx_data) +{ + if (selctx_data->do_free) { + if (selctx_data->elems) { + MEM_freeN(selctx_data->elems); + } + } + + but->flag &= ~UI_BUT_IS_SELECT_CONTEXT; +} + +static void ui_selectcontext_apply( + bContext *C, uiBut *but, uiSelectContextStore *selctx_data, + const double value, const double value_orig) +{ + if (selctx_data->elems) { + PropertyRNA *prop = but->rnaprop; + PropertyRNA *lprop = but->rnaprop; + int index = but->rnaindex; + int i; + const bool use_delta = (selctx_data->is_copy == false); + + union { + bool b; + int i; + float f; + } delta, min, max; + + const bool is_array = RNA_property_array_check(prop); + const int rna_type = RNA_property_type(prop); + + if (rna_type == PROP_FLOAT) { + delta.f = use_delta ? (value - value_orig) : value; + RNA_property_float_range(&but->rnapoin, prop, &min.f, &max.f); + } + else if (rna_type == PROP_INT) { + delta.i = use_delta ? ((int)value - (int)value_orig) : (int)value; + RNA_property_int_range(&but->rnapoin, prop, &min.i, &max.i); + } + else if (rna_type == PROP_ENUM) { + delta.i = RNA_property_enum_get(&but->rnapoin, prop); /* not a delta infact */ + } + else if (rna_type == PROP_BOOLEAN) { + if (is_array) { + delta.b = RNA_property_boolean_get_index(&but->rnapoin, prop, index); /* not a delta infact */ + } + else { + delta.b = RNA_property_boolean_get(&but->rnapoin, prop); /* not a delta infact */ + } + } + +#ifdef USE_ALLSELECT_LAYER_HACK + /* make up for not having 'handle_layer_buttons' */ + { + PropertySubType subtype = RNA_property_subtype(prop); + + if ((rna_type == PROP_BOOLEAN) && + ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER) && + is_array && + /* could check for 'handle_layer_buttons' */ + but->func) + { + wmWindow *win = CTX_wm_window(C); + if (!win->eventstate->shift) { + const int len = RNA_property_array_length(&but->rnapoin, prop); + int *tmparray = MEM_callocN(sizeof(int) * len, __func__); + + tmparray[index] = true; + + for (i = 0; i < selctx_data->elems_len; i++) { + uiSelectContextElem *other = &selctx_data->elems[i]; + PointerRNA lptr = other->ptr; + RNA_property_boolean_set_array(&lptr, lprop, tmparray); + RNA_property_update(C, &lptr, lprop); + } + + MEM_freeN(tmparray); + + return; + } + } + } +#endif + + for (i = 0; i < selctx_data->elems_len; i++) { + uiSelectContextElem *other = &selctx_data->elems[i]; + PointerRNA lptr = other->ptr; + + if (rna_type == PROP_FLOAT) { + float other_value = use_delta ? (other->val_f + delta.f) : delta.f; + CLAMP(other_value, min.f, max.f); + if (is_array) { + RNA_property_float_set_index(&lptr, lprop, index, other_value); + } + else { + RNA_property_float_set(&lptr, lprop, other_value); + } + } + else if (rna_type == PROP_INT) { + int other_value = use_delta ? (other->val_i + delta.i) : delta.i; + CLAMP(other_value, min.i, max.i); + if (is_array) { + RNA_property_int_set_index(&lptr, lprop, index, other_value); + } + else { + RNA_property_int_set(&lptr, lprop, other_value); + } + } + else if (rna_type == PROP_BOOLEAN) { + const bool other_value = delta.b; + if (is_array) { + RNA_property_boolean_set_index(&lptr, lprop, index, other_value); + } + else { + RNA_property_boolean_set(&lptr, lprop, delta.b); + } + } + else if (rna_type == PROP_ENUM) { + const int other_value = delta.i; + BLI_assert(!is_array); + RNA_property_enum_set(&lptr, lprop, other_value); + } + + RNA_property_update(C, &lptr, prop); + } + } +} + +#endif /* USE_ALLSELECT */ + + static bool ui_but_contains_point_px_icon(uiBut *but, ARegion *ar, const wmEvent *event) { rcti rect; @@ -1278,10 +1642,11 @@ static bool ui_but_drag_init(bContext *C, uiBut *but, uiHandleButtonData *data, ar_prev = CTX_wm_region(C); CTX_wm_region_set(C, data->region); - WM_event_add_ui_handler(C, &data->window->modalhandlers, - ui_handler_region_drag_toggle, - ui_handler_region_drag_toggle_remove, - drag_info, false); + WM_event_add_ui_handler( + C, &data->window->modalhandlers, + ui_handler_region_drag_toggle, + ui_handler_region_drag_toggle_remove, + drag_info, WM_HANDLER_BLOCKING); CTX_wm_region_set(C, ar_prev); } @@ -1596,9 +1961,8 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton data->str = data->origstr; data->origstr = NULL; data->value = data->origvalue; - data->origvalue = 0.0; copy_v3_v3(data->vec, data->origvec); - data->origvec[0] = data->origvec[1] = data->origvec[2] = 0.0f; + /* postpone clearing origdata */ } else { /* we avoid applying interactive edits a second time @@ -1609,6 +1973,27 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton else if (data->applied_interactive) { return; } + +#ifdef USE_ALLSELECT +# ifdef USE_DRAG_MULTINUM + if (but->flag & UI_BUT_DRAG_MULTI) { + /* pass */ + } + else +# endif + if (data->select_others.elems_len == 0) { + wmWindow *win = CTX_wm_window(C); + /* may have been enabled before activating */ + if (data->select_others.is_enabled || IS_ALLSELECT_EVENT(win->eventstate)) { + ui_selectcontext_begin(C, but, &data->select_others); + data->select_others.is_enabled = true; + } + } + if (data->select_others.elems_len == 0) { + /* dont check again */ + data->select_others.elems_len = -1; + } +#endif } /* ensures we are writing actual values */ @@ -1629,7 +2014,6 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton ui_apply_but_BUT(C, but, data); break; case UI_BTYPE_TEXT: - case UI_BTYPE_SEARCH_MENU_UNLINK: case UI_BTYPE_SEARCH_MENU: ui_apply_but_TEX(C, but, data); break; @@ -1705,7 +2089,7 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton if (data->multi_data.has_mbuts) { if (data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) { if (data->cancel) { - ui_multibut_restore(data, block); + ui_multibut_restore(C, data, block); } else { ui_multibut_states_apply(C, data, block); @@ -1714,6 +2098,15 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton } #endif +#ifdef USE_ALLSELECT + ui_selectcontext_apply(C, but, &data->select_others, data->value, data->origvalue); +#endif + + if (data->cancel) { + data->origvalue = 0.0; + zero_v3(data->origvec); + } + but->editstr = editstr; but->editval = editval; but->editvec = editvec; @@ -1732,13 +2125,13 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB for (wmd = drags->first; wmd; wmd = wmd->next) { if (wmd->type == WM_DRAG_ID) { /* align these types with UI_but_active_drop_name */ - if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { ID *id = (ID *)wmd->poin; button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); BLI_strncpy(data->str, id->name + 2, data->maxlen); - if (ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (ELEM(but->type, UI_BTYPE_SEARCH_MENU)) { but->changed = true; ui_searchbox_update(C, data->searchbox, but, true); } @@ -1879,7 +2272,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, } /* text/string and ID data */ - else if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + else if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { uiHandleButtonData *active_data = but->active; if (but->poin == NULL && but->rnapoin.data == NULL) { @@ -1899,7 +2292,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, else BLI_strncpy(active_data->str, buf_paste, active_data->maxlen); - if (ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (but->type == UI_BTYPE_SEARCH_MENU) { /* else uiSearchboxData.active member is not updated [#26856] */ but->changed = true; ui_searchbox_update(C, data->searchbox, but, true); @@ -1974,15 +2367,17 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, } } -/* ************************ password text ****************************** +/** + * Password Text + * ============= * * Functions to convert password strings that should not be displayed - * to asterisk representation (e.g. mysecretpasswd -> *************) + * to asterisk representation (e.g. 'mysecretpasswd' -> '*************') * * It converts every UTF-8 character to an asterisk, and also remaps * the cursor position and selection start/end. * - * Note: remaping is used, because password could contain UTF-8 characters. + * \note: remaping is used, because password could contain UTF-8 characters. * */ @@ -2092,7 +2487,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con BLI_strncpy(origstr, but->editstr, data->maxlen); - if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { if (but->flag & UI_HAS_ICON) { startx += UI_DPI_ICON_SIZE / aspect; } @@ -2182,11 +2577,13 @@ static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, ui_but_update(but); } -/* this is used for both utf8 and ascii, its meant to be used for single keys, +/** + * This is used for both utf8 and ascii, its meant to be used for single keys, * notice the buffer is either copied or not, so its not suitable for pasting in * - campbell */ -static bool ui_textedit_type_buf(uiBut *but, uiHandleButtonData *data, - const char *utf8_buf, int utf8_buf_len) +static bool ui_textedit_type_buf( + uiBut *but, uiHandleButtonData *data, + const char *utf8_buf, int utf8_buf_len) { char *str; int len; @@ -2230,8 +2627,9 @@ static bool ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char as return ui_textedit_type_buf(but, data, buf, 1); } -static void ui_textedit_move(uiBut *but, uiHandleButtonData *data, strCursorJumpDirection direction, - const bool select, strCursorJumpType jump) +static void ui_textedit_move( + uiBut *but, uiHandleButtonData *data, strCursorJumpDirection direction, + const bool select, strCursorJumpType jump) { const char *str = data->str; const int len = strlen(str); @@ -2447,6 +2845,18 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in } #ifdef WITH_INPUT_IME +/* test if the translation context allows IME input - used to + * avoid weird character drawing if IME inputs non-ascii chars */ +static bool ui_ime_is_lang_supported(void) +{ + const char *uilng = BLF_lang_get(); + const bool is_lang_supported = STREQ(uilng, "zh_CN") || + STREQ(uilng, "zh_TW") || + STREQ(uilng, "ja_JP"); + + return ((U.transopts & USER_DOTRANSLATE) && is_lang_supported); +} + /* enable ime, and set up uibut ime data */ static void ui_textedit_ime_begin(wmWindow *win, uiBut *UNUSED(but)) { @@ -2477,8 +2887,7 @@ void ui_but_ime_reposition(uiBut *but, int x, int y, bool complete) wm_window_IME_begin(but->active->window, x, y - 4, 0, 0, complete); } -/* should be ui_but_ime_data_get */ -wmIMEData *ui_but_get_ime_data(uiBut *but) +wmIMEData *ui_but_ime_data_get(uiBut *but) { if (but->active && but->active->window) { return but->active->window->ime_data; @@ -2512,6 +2921,16 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) } #endif +#ifdef USE_ALLSELECT + if (is_num_but) { + if (IS_ALLSELECT_EVENT(win->eventstate)) { + data->select_others.is_enabled = true; + data->select_others.is_copy = true; + + } + } +#endif + /* retrieve string */ data->maxlen = ui_but_string_get_max_length(but); data->str = MEM_callocN(sizeof(char) * data->maxlen + 1, "textedit str"); @@ -2539,7 +2958,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) but->selend = len; /* optional searchbox */ - if (ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (but->type == UI_BTYPE_SEARCH_MENU) { data->searchbox = ui_searchbox_create(C, data->region, but); ui_searchbox_update(C, data->searchbox, but, true); /* true = reset */ } @@ -2552,7 +2971,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) WM_cursor_modal_set(win, BC_TEXTEDITCURSOR); #ifdef WITH_INPUT_IME - if (is_num_but == false) { + if (is_num_but == false && ui_ime_is_lang_supported()) { ui_textedit_ime_begin(win, but); } #endif @@ -2789,6 +3208,9 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle ui_searchbox_event(C, data->searchbox, but, event); break; } + if (event->type == WHEELDOWNMOUSE) { + break; + } /* fall-through */ case ENDKEY: ui_textedit_move(but, data, STRCUR_DIR_NEXT, @@ -2804,6 +3226,9 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle ui_searchbox_event(C, data->searchbox, but, event); break; } + if (event->type == WHEELUPMOUSE) { + break; + } /* fall-through */ case HOMEKEY: ui_textedit_move(but, data, STRCUR_DIR_PREV, @@ -2854,8 +3279,6 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle if (autocomplete == AUTOCOMPLETE_FULL_MATCH) button_activate_state(C, but, BUTTON_STATE_EXIT); - - update = true; /* do live update for tab key */ } /* the hotkey here is not well defined, was G.qual so we check all */ else if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) { @@ -2934,7 +3357,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle #endif if (changed) { - /* only update when typing for TAB key */ + /* only do live update when but flag request it (UI_BUT_TEXTEDIT_UPDATE). */ if (update && data->interactive) { ui_apply_but(C, block, but, data, true); } @@ -3092,6 +3515,15 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat data->menu->popup = but->block->handle->popup; } +#ifdef USE_ALLSELECT + { + wmWindow *win = CTX_wm_window(C); + if (IS_ALLSELECT_EVENT(win->eventstate)) { + data->select_others.is_enabled = true; + } + } +#endif + /* this makes adjacent blocks auto open from now on */ //if (but->block->auto_open == 0) but->block->auto_open = 1; } @@ -3121,9 +3553,13 @@ int ui_but_menu_direction(uiBut *but) return 0; } -/* Hack for uiList UI_BTYPE_LISTROW buttons to "give" events to overlaying UI_BTYPE_TEXT buttons (cltr-clic rename feature & co). */ -static uiBut *ui_but_list_row_text_activate(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event, - uiButtonActivateType activate_type) +/** + * Hack for #uiList #UI_BTYPE_LISTROW buttons to "give" events to overlaying #UI_BTYPE_TEXT buttons + * (Ctrl-Click rename feature & co). + */ +static uiBut *ui_but_list_row_text_activate( + bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event, + uiButtonActivateType activate_type) { ARegion *ar = CTX_wm_region(C); uiBut *labelbut = ui_but_find_mouse_over_ex(ar, event->x, event->y, true); @@ -3293,9 +3729,11 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) { + uiButExtraIconType extra_icon_type; + /* unlink icon is on right */ - if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS && - ui_but_is_search_unlink_visible(but)) + if ((ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY)) && + ((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE)) { ARegion *ar = data->region; rcti rect; @@ -3306,14 +3744,29 @@ static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHa BLI_rcti_rctf_copy(&rect, &but->rect); rect.xmin = rect.xmax - (BLI_rcti_size_y(&rect)); + /* handle click on unlink/eyedropper icon */ if (BLI_rcti_isect_pt(&rect, x, y)) { - /* most likely NULL, but let's check, and give it temp zero string */ - if (data->str == NULL) - data->str = MEM_callocN(1, "temp str"); - data->str[0] = 0; + /* doing this on KM_PRESS calls eyedropper after clicking unlink icon */ + if (event->val == KM_RELEASE) { + /* unlink */ + if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) { + /* most likely NULL, but let's check, and give it temp zero string */ + if (data->str == NULL) { + data->str = MEM_callocN(1, "temp str"); + } + data->str[0] = 0; - ui_apply_but_TEX(C, but, data); - button_activate_state(C, but, BUTTON_STATE_EXIT); + ui_apply_but_TEX(C, but, data); + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + /* eyedropper */ + else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) { + WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL); + } + else { + BLI_assert(0); + } + } return WM_UI_HANDLER_BREAK; } @@ -3352,7 +3805,7 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons button_activate_state(C, but, BUTTON_STATE_EXIT); return WM_UI_HANDLER_BREAK; } - else if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) { + else if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { /* Support alt+wheel on expanded enum rows */ if (but->type == UI_BTYPE_ROW) { const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1; @@ -3448,8 +3901,9 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con } /* var names match ui_numedit_but_NUM */ -static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, float softmax, float softrange, - const enum eSnapType snap) +static float ui_numedit_apply_snapf( + uiBut *but, float tempf, float softmin, float softmax, float softrange, + const enum eSnapType snap) { if (tempf == softmin || tempf == softmax || snap == SNAP_OFF) { /* pass */ @@ -3477,15 +3931,25 @@ static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, floa softrange /= fac; } + /* workaround, too high snapping values */ + /* snapping by 10's for float buttons is quite annoying (location, scale...), + * but allow for rotations */ + if ((softrange > 2100.0f)) { + int unit_type = UI_but_unit_type_get(but); + if (!ELEM(unit_type, PROP_UNIT_ROTATION)) { + softrange = 20.0f; + } + } + if (snap == SNAP_ON) { - if (softrange < 2.10f) tempf = 0.1f * floorf(10.0f * tempf); - else if (softrange < 21.0f) tempf = floorf(tempf); - else tempf = 10.0f * floorf(tempf / 10.0f); + if (softrange < 2.10f) tempf = roundf(tempf * 10.0f) * 0.1f; + else if (softrange < 21.0f) tempf = roundf(tempf); + else tempf = roundf(tempf * 0.1f) * 10.0f; } else if (snap == SNAP_ON_SMALL) { - if (softrange < 2.10f) tempf = 0.01f * floorf(100.0f * tempf); - else if (softrange < 21.0f) tempf = 0.1f * floorf(10.0f * tempf); - else tempf = floor(tempf); + if (softrange < 2.10f) tempf = roundf(tempf * 100.0f) * 0.01f; + else if (softrange < 21.0f) tempf = roundf(tempf * 10.0f) * 0.1f; + else tempf = roundf(tempf); } else { BLI_assert(0); @@ -3498,8 +3962,9 @@ static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, floa return tempf; } -static float ui_numedit_apply_snap(int temp, float softmin, float softmax, - const enum eSnapType snap) +static float ui_numedit_apply_snap( + int temp, float softmin, float softmax, + const enum eSnapType snap) { if (temp == softmin || temp == softmax) return temp; @@ -3518,9 +3983,10 @@ static float ui_numedit_apply_snap(int temp, float softmin, float softmax, return temp; } -static bool ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, - int mx, - const enum eSnapType snap, float fac) +static bool ui_numedit_but_NUM( + uiBut *but, uiHandleButtonData *data, + int mx, + const enum eSnapType snap, float fac) { float deler, tempf, softmin, softmax, softrange; int lvalue, temp; @@ -3636,7 +4102,7 @@ static bool ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, if (!is_float) { - temp = floorf(tempf + 0.5f); + temp = iroundf(tempf); temp = ui_numedit_apply_snap(temp, softmin, softmax, snap); @@ -3689,11 +4155,11 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton /* XXX hardcoded keymap check.... */ if (type == MOUSEPAN && event->alt) retval = WM_UI_HANDLER_BREAK; /* allow accumulating values, otherwise scrolling gets preference */ - else if (type == WHEELDOWNMOUSE && event->alt) { + else if (type == WHEELDOWNMOUSE && event->ctrl) { mx = but->rect.xmin; click = 1; } - else if (type == WHEELUPMOUSE && event->alt) { + else if (type == WHEELUPMOUSE && event->ctrl) { mx = but->rect.xmax; click = 1; } @@ -3759,7 +4225,6 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton fac = 1.0f; if (event->shift) fac /= 10.0f; - if (event->alt) fac /= 20.0f; if (ui_numedit_but_NUM(but, data, (ui_but_is_cursor_warp(but) ? screen_mx : mx), snap, fac)) ui_numedit_apply(C, block, but, data); @@ -3854,9 +4319,10 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton return retval; } -static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, - int mx, const bool is_horizontal, - const bool snap, const bool shift) +static bool ui_numedit_but_SLI( + uiBut *but, uiHandleButtonData *data, + int mx, const bool is_horizontal, + const bool snap, const bool shift) { float deler, f, tempf, softmin, softmax, softrange; int temp, lvalue; @@ -3909,7 +4375,7 @@ static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, tempf = softmin + f * softrange; - temp = floorf(tempf + 0.5f); + temp = iroundf(tempf); if (snap) { if (tempf == softmin || tempf == softmax) { @@ -3919,14 +4385,14 @@ static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, if (shift) { if (tempf == softmin || tempf == softmax) {} - else if (softmax - softmin < 2.10f) tempf = 0.01f * floorf(100.0f * tempf); - else if (softmax - softmin < 21.0f) tempf = 0.1f * floorf(10.0f * tempf); - else tempf = floorf(tempf); + else if (softrange < 2.10f) tempf = roundf(tempf * 100.0f) * 0.01f; + else if (softrange < 21.0f) tempf = roundf(tempf * 10.0f) * 0.1f; + else tempf = roundf(tempf); } else { - if (softmax - softmin < 2.10f) tempf = 0.1f * floorf(10.0f * tempf); - else if (softmax - softmin < 21.0f) tempf = floorf(tempf); - else tempf = 10.0f * floorf(tempf / 10.0f); + if (softrange < 2.10f) tempf = roundf(tempf * 10.0f) * 0.1f; + else if (softrange < 21.0f) tempf = roundf(tempf); + else tempf = roundf(tempf * 0.1f) * 10.0f; } } else { @@ -3936,7 +4402,7 @@ static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, } if (!ui_but_is_float(but)) { - lvalue = floor(data->value + 0.5); + lvalue = round(data->value); CLAMP(temp, softmin, softmax); @@ -3978,11 +4444,11 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton /* XXX hardcoded keymap check.... */ if (type == MOUSEPAN && event->alt) retval = WM_UI_HANDLER_BREAK; /* allow accumulating values, otherwise scrolling gets preference */ - else if (type == WHEELDOWNMOUSE && event->alt) { + else if (type == WHEELDOWNMOUSE && event->ctrl) { mx = but->rect.xmin; click = 2; } - else if (type == WHEELUPMOUSE && event->alt) { + else if (type == WHEELUPMOUSE && event->ctrl) { mx = but->rect.xmax; click = 2; } @@ -3991,6 +4457,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); retval = WM_UI_HANDLER_BREAK; } +#ifndef USE_ALLSELECT /* alt-click on sides to get "arrows" like in UI_BTYPE_NUM buttons, and match wheel usage above */ else if (event->type == LEFTMOUSE && event->alt) { int halfpos = BLI_rctf_cent_x(&but->rect); @@ -4000,6 +4467,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton else mx = but->rect.xmax; } +#endif else if (event->type == LEFTMOUSE) { data->dragstartx = mx; data->draglastx = mx; @@ -4286,7 +4754,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co return WM_UI_HANDLER_BREAK; } else if (but->type == UI_BTYPE_MENU) { - if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) { + if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1; data->value = ui_but_menu_step(but, direction); @@ -4342,9 +4810,10 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co return WM_UI_HANDLER_CONTINUE; } -static bool ui_numedit_but_UNITVEC(uiBut *but, uiHandleButtonData *data, - int mx, int my, - const enum eSnapType snap) +static bool ui_numedit_but_UNITVEC( + uiBut *but, uiHandleButtonData *data, + int mx, int my, + const enum eSnapType snap) { float dx, dy, rad, radsq, mrad, *fp; int mdx, mdy; @@ -4410,7 +4879,7 @@ static bool ui_numedit_but_UNITVEC(uiBut *but, uiHandleButtonData *data, * do this in "angle" space - this gives increments of same size */ for (i = 0; i < 3; i++) { angle = asinf(fp[i]); - angle_snap = floorf(0.5f + (angle / snap_steps_angle)) * snap_steps_angle; + angle_snap = roundf((angle / snap_steps_angle)) * snap_steps_angle; fp[i] = sinf(angle_snap); } normalize_v3(fp); @@ -4460,7 +4929,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co button_activate_state(C, but, BUTTON_STATE_MENU_OPEN); return WM_UI_HANDLER_BREAK; } - else if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) { + else if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { ColorPicker *cpicker = but->custom_data; float hsv_static[3] = {0.0f}; float *hsv = cpicker ? cpicker->color_data : hsv_static; @@ -4494,6 +4963,12 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co BKE_palette_color_remove(palette, color); button_activate_state(C, but, BUTTON_STATE_EXIT); + + /* this is risky. it works OK for now, + * but if it gives trouble we should delay execution */ + but->rnapoin = PointerRNA_NULL; + but->rnaprop = NULL; + return WM_UI_HANDLER_BREAK; } } @@ -4638,9 +5113,10 @@ static void ui_color_picker_to_rgb_HSVCUBE_v(uiBut *but, const float hsv[3], flo hsv_to_rgb_v(hsv, rgb); } -static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, - int mx, int my, - const enum eSnapType snap, const bool shift) +static bool ui_numedit_but_HSVCUBE( + uiBut *but, uiHandleButtonData *data, + int mx, int my, + const enum eSnapType snap, const bool shift) { ColorPicker *cpicker = but->custom_data; float *hsv = cpicker->color_data; @@ -4699,8 +5175,8 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, switch ((int)but->a1) { case UI_GRAD_SV: - hsv[2] = x; - hsv[1] = y; + hsv[1] = x; + hsv[2] = y; break; case UI_GRAD_HV: hsv[0] = x; @@ -4757,9 +5233,10 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, return changed; } -static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, - const wmNDOFMotionData *ndof, - const enum eSnapType snap, const bool shift) +static void ui_ndofedit_but_HSVCUBE( + uiBut *but, uiHandleButtonData *data, + const wmNDOFMotionData *ndof, + const enum eSnapType snap, const bool shift) { ColorPicker *cpicker = but->custom_data; float *hsv = cpicker->color_data; @@ -4777,8 +5254,8 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, switch ((int)but->a1) { case UI_GRAD_SV: - hsv[2] += ndof->rvec[2] * sensitivity; - hsv[1] += ndof->rvec[0] * sensitivity; + hsv[1] += ndof->rvec[2] * sensitivity; + hsv[2] += ndof->rvec[0] * sensitivity; break; case UI_GRAD_HV: hsv[0] += ndof->rvec[2] * sensitivity; @@ -4922,9 +5399,10 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu return WM_UI_HANDLER_CONTINUE; } -static bool ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, - float mx, float my, - const enum eSnapType snap, const bool shift) +static bool ui_numedit_but_HSVCIRCLE( + uiBut *but, uiHandleButtonData *data, + float mx, float my, + const enum eSnapType snap, const bool shift) { rcti rect; bool changed = true; @@ -5019,9 +5497,10 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, return changed; } -static void ui_ndofedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, - const wmNDOFMotionData *ndof, - const enum eSnapType snap, const bool shift) +static void ui_ndofedit_but_HSVCIRCLE( + uiBut *but, uiHandleButtonData *data, + const wmNDOFMotionData *ndof, + const enum eSnapType snap, const bool shift) { ColorPicker *cpicker = but->custom_data; float *hsv = cpicker->color_data; @@ -5280,7 +5759,8 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle return WM_UI_HANDLER_CONTINUE; } -static bool ui_numedit_but_CURVE(uiBlock *block, uiBut *but, uiHandleButtonData *data, +static bool ui_numedit_but_CURVE( + uiBlock *block, uiBut *but, uiHandleButtonData *data, int evtx, int evty, bool snap, const bool shift) { @@ -5330,8 +5810,8 @@ static bool ui_numedit_but_CURVE(uiBlock *block, uiBut *but, uiHandleButtonData cmp[a].x += fx; cmp[a].y += fy; if (snap) { - cmp[a].x = 0.125f * floorf(0.5f + 8.0f * cmp[a].x); - cmp[a].y = 0.125f * floorf(0.5f + 8.0f * cmp[a].y); + cmp[a].x = 0.125f * roundf(8.0f * cmp[a].x); + cmp[a].y = 0.125f * roundf(8.0f * cmp[a].y); } if (cmp[a].x != origx || cmp[a].y != origy) moved_point = true; @@ -5714,9 +6194,10 @@ static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, con return WM_UI_HANDLER_CONTINUE; } -static bool ui_numedit_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonData *data, - int mx, int my, - const bool shift) +static bool ui_numedit_but_TRACKPREVIEW( + bContext *C, uiBut *but, uiHandleButtonData *data, + int mx, int my, + const bool shift) { MovieClipScopes *scopes = (MovieClipScopes *)but->poin; bool changed = true; @@ -5925,7 +6406,7 @@ static void menu_add_shortcut_cancel(struct bContext *C, void *arg1) static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) { uiBut *but = (uiBut *)arg1; - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); UI_popup_block_invoke(C, menu_change_shortcut, but); } @@ -5946,7 +6427,7 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) { uiBut *but = (uiBut *)arg1; - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but); } @@ -5995,7 +6476,7 @@ static bool ui_but_menu(bContext *C, uiBut *but) return false; } - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); /* highly unlikely getting the label ever fails */ UI_but_string_info_get(C, but, &label, NULL); @@ -6064,7 +6545,7 @@ static bool ui_but_menu(bContext *C, uiBut *but) } } - if (but->flag & UI_BUT_ANIMATED) { + if ((but->flag & UI_BUT_ANIMATED) && (but->rnapoin.type != &RNA_NlaStrip)) { if (is_array_component) { uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"), ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 1); @@ -6211,7 +6692,7 @@ static bool ui_but_menu(bContext *C, uiBut *but) } /* Show header tools for header buttons. */ - { + if (ui_block_is_menu(but->block) == false) { ARegion *ar = CTX_wm_region(C); if (ar && (ar->regiontype == RGN_TYPE_HEADER)) { uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL); @@ -6223,14 +6704,9 @@ static bool ui_but_menu(bContext *C, uiBut *but) char buf[512]; PointerRNA ptr_props; - if (but->rnapoin.data && but->rnaprop) { - BLI_snprintf(buf, sizeof(buf), "%s.%s", - RNA_struct_identifier(but->rnapoin.type), RNA_property_identifier(but->rnaprop)); - - WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual"); - RNA_string_set(&ptr_props, "doc_id", buf); - uiItemFullO(layout, "WM_OT_doc_view_manual", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), - ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0); + if (UI_but_online_manual_id(but, buf, sizeof(buf))) { + uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), + ICON_NONE, "WM_OT_doc_view_manual_ui_context"); WM_operator_properties_create(&ptr_props, "WM_OT_doc_view"); RNA_string_set(&ptr_props, "doc_id", buf); @@ -6246,30 +6722,6 @@ static bool ui_but_menu(bContext *C, uiBut *but) uiItemFullO(layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0); #endif } - else if (but->optype) { - WM_operator_py_idname(buf, but->optype->idname); - - - WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual"); - RNA_string_set(&ptr_props, "doc_id", buf); - uiItemFullO(layout, "WM_OT_doc_view_manual", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), - ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create(&ptr_props, "WM_OT_doc_view"); - RNA_string_set(&ptr_props, "doc_id", buf); - uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), - ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0); - - /* XXX inactive option, not for public! */ -#if 0 - WM_operator_properties_create(&ptr_props, "WM_OT_doc_edit"); - RNA_string_set(&ptr_props, "doc_id", buf); - RNA_string_set(&ptr_props, "doc_new", but->optype->description); - - uiItemFullO(layout, "WM_OT_doc_edit", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Submit Description"), - ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0); -#endif - } } /* perhaps we should move this into (G.debug & G_DEBUG) - campbell */ @@ -6325,7 +6777,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * WM_operator_name_call(C, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, NULL); return WM_UI_HANDLER_BREAK; } - else if (but->type == UI_BTYPE_SEARCH_MENU_UNLINK) { + else if ((but->type == UI_BTYPE_SEARCH_MENU) && + (but->flag & UI_BUT_SEARCH_UNLINK)) + { if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_POINTER) { StructRNA *type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop); const short idcode = RNA_type_to_ID_code(type); @@ -6482,11 +6936,16 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * break; case UI_BTYPE_TEXT: case UI_BTYPE_SEARCH_MENU: + if ((but->type == UI_BTYPE_SEARCH_MENU) && + (but->flag & UI_BUT_SEARCH_UNLINK)) + { + retval = ui_do_but_SEARCH_UNLINK(C, block, but, data, event); + if (retval & WM_UI_HANDLER_BREAK) { + break; + } + } retval = ui_do_but_TEX(C, block, but, data, event); break; - case UI_BTYPE_SEARCH_MENU_UNLINK: - retval = ui_do_but_SEARCH_UNLINK(C, block, but, data, event); - break; case UI_BTYPE_MENU: case UI_BTYPE_BLOCK: case UI_BTYPE_PULLDOWN: @@ -6586,8 +7045,13 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * /* just to be sure, check we're dragging more hoz then virt */ abs(event->prevx - event->x) > abs(event->prevy - event->y))) { - ui_multibut_states_create(but, data); - data->multi_data.init = BUTTON_MULTI_INIT_ENABLE; + if (data->multi_data.has_mbuts) { + ui_multibut_states_create(but, data); + data->multi_data.init = BUTTON_MULTI_INIT_ENABLE; + } + else { + data->multi_data.init = BUTTON_MULTI_INIT_DISABLE; + } } } @@ -6725,7 +7189,7 @@ bool UI_but_active_drop_name(bContext *C) uiBut *but = ui_but_find_active_in_region(ar); if (but) { - if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) + if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) return 1; } @@ -6840,13 +7304,6 @@ static bool ui_but_is_interactive(const uiBut *but, const bool labeledit) return true; } -bool ui_but_is_search_unlink_visible(const uiBut *but) -{ - BLI_assert(but->type == UI_BTYPE_SEARCH_MENU_UNLINK); - return ((but->editstr == NULL) && - (but->drawstr[0] != '\0')); -} - /* x and y are only used in case event is NULL... */ static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit) { @@ -6934,7 +7391,8 @@ static bool button_modal_state(uiHandleButtonState state) BUTTON_STATE_MENU_OPEN); } -static void button_timers_tooltip_remove(bContext *C, uiBut *but) +/* removes tooltip timer from active but (meaning tooltip is disabled until it's reenabled again) */ +void UI_but_tooltip_timer_remove(bContext *C, uiBut *but) { uiHandleButtonData *data; @@ -7018,7 +7476,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s } else { but->flag |= UI_SELECT; - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); } /* text editing */ @@ -7080,7 +7538,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s if (!(but->block->handle && but->block->handle->popup)) { if (button_modal_state(state)) { if (!button_modal_state(data->state)) - WM_event_add_ui_handler(C, &data->window->modalhandlers, ui_handler_region_menu, NULL, data, false); + WM_event_add_ui_handler(C, &data->window->modalhandlers, ui_handler_region_menu, NULL, data, 0); } else { if (button_modal_state(data->state)) { @@ -7125,7 +7583,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA copy_v2_fl(data->ungrab_mval, FLT_MAX); #endif - if (ELEM(but->type, UI_BTYPE_CURVE, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (ELEM(but->type, UI_BTYPE_CURVE, UI_BTYPE_SEARCH_MENU)) { /* XXX curve is temp */ } else { @@ -7185,8 +7643,9 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA } } -static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *data, - const bool mousemove, const bool onfree) +static void button_activate_exit( + bContext *C, uiBut *but, uiHandleButtonData *data, + const bool mousemove, const bool onfree) { uiBlock *block = but->block; uiBut *bt; @@ -7258,6 +7717,10 @@ static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *da if (data->origstr) MEM_freeN(data->origstr); +#ifdef USE_ALLSELECT + ui_selectcontext_end(but, &data->select_others); +#endif + /* redraw (data is but->active!) */ ED_region_tag_redraw(data->region); @@ -7464,7 +7927,7 @@ void UI_context_update_anim_flag(const bContext *C) /************** handle activating a button *************/ -static uiBut *uit_but_find_open_event(ARegion *ar, const wmEvent *event) +static uiBut *ui_but_find_open_event(ARegion *ar, const wmEvent *event) { uiBlock *block; uiBut *but; @@ -7495,7 +7958,7 @@ static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *ar) } } else if (event->type == EVT_BUT_OPEN) { - but = uit_but_find_open_event(ar, event); + but = ui_but_find_open_event(ar, event); if (but) { button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER); ui_do_button(C, but->block, but, event); @@ -7599,7 +8062,8 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) uiBut *but_other = ui_but_find_mouse_over(ar, event); bool exit = false; - if ((!ui_block_is_menu(block) || ui_block_is_pie_menu(but->block)) && + /* always deactivate button for pie menus, else moving to blank space will leave activated */ + if ((!ui_block_is_menu(block) || ui_block_is_pie_menu(block)) && !ui_but_contains_point_px(ar, but, event->x, event->y)) { exit = true; @@ -7647,7 +8111,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) case WHEELDOWNMOUSE: case MIDDLEMOUSE: case MOUSEPAN: - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); /* fall-through */ default: /* handle button type specific events */ @@ -7808,7 +8272,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar) if (val == KM_PRESS) { if (ELEM(type, UPARROWKEY, DOWNARROWKEY) || - ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt))) + ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->ctrl))) { const int value_orig = RNA_property_int_get(&but->rnapoin, but->rnaprop); int value, min, max, inc; @@ -7958,13 +8422,14 @@ static void ui_handle_button_return_submenu(bContext *C, const wmEvent *event, u /* ************************* menu handling *******************************/ -/* function used to prevent loosing the open menu when using nested pulldowns, +/** + * Function used to prevent loosing the open menu when using nested pulldowns, * when moving mouse towards the pulldown menu over other buttons that could * steal the highlight from the current button, only checks: * * - while mouse moves in triangular area defined old mouse position and - * left/right side of new menu - * - only for 1 second + * left/right side of new menu. + * - only for 1 second. */ static void ui_mouse_motion_towards_init_ex(uiPopupBlockHandle *menu, const int xy[2], const bool force) @@ -7993,8 +8458,9 @@ static void ui_mouse_motion_towards_reinit(uiPopupBlockHandle *menu, const int x ui_mouse_motion_towards_init_ex(menu, xy, true); } -static bool ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *menu, const int xy[2], - const bool use_wiggle_room) +static bool ui_mouse_motion_towards_check( + uiBlock *block, uiPopupBlockHandle *menu, const int xy[2], + const bool use_wiggle_room) { float p1[2], p2[2], p3[2], p4[2]; float oldp[2] = {menu->towards_xy[0], menu->towards_xy[1]}; @@ -8182,8 +8648,9 @@ static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my, uiBut *to_bt) * * Without this keyboard navigation from menu's wont work. */ -static bool ui_menu_pass_event_to_parent_if_nonactive(uiPopupBlockHandle *menu, const uiBut *but, - const int level, const int retval) +static bool ui_menu_pass_event_to_parent_if_nonactive( + uiPopupBlockHandle *menu, const uiBut *but, + const int level, const int retval) { if ((level != 0) && (but == NULL)) { menu->menuretval = UI_RETURN_OUT | UI_RETURN_OUT_PARENT; @@ -8553,7 +9020,7 @@ static int ui_handle_menu_event( ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE); } else { - printf("%s: error, but->menu_key type: %d\n", __func__, but->type); + printf("%s: error, but->menu_key type: %u\n", __func__, but->type); } break; @@ -8622,7 +9089,7 @@ static int ui_handle_menu_event( { if (!but || !ui_but_contains_point_px(ar, but, event->x, event->y)) { if (but) { - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); } menu->is_grab = true; @@ -8701,6 +9168,9 @@ static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPo block = ar->uiblocks.first; but = ui_but_find_active_in_region(ar); + + BLI_assert(but); + data = but->active; submenu = data->menu; @@ -9100,7 +9570,7 @@ static int ui_handle_menus_recursive( /* now handle events for our own menu */ if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) { - const bool do_but_search = (but && ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)); + const bool do_but_search = (but && (but->type == UI_BTYPE_SEARCH_MENU)); if (submenu && submenu->menuretval) { const bool do_ret_out_parent = (submenu->menuretval & UI_RETURN_OUT_PARENT) != 0; retval = ui_handle_menu_return_submenu(C, event, menu); @@ -9384,12 +9854,12 @@ static void ui_popup_handler_remove(bContext *C, void *userdata) void UI_region_handlers_add(ListBase *handlers) { WM_event_remove_ui_handler(handlers, ui_region_handler, ui_region_handler_remove, NULL, false); - WM_event_add_ui_handler(NULL, handlers, ui_region_handler, ui_region_handler_remove, NULL, false); + WM_event_add_ui_handler(NULL, handlers, ui_region_handler, ui_region_handler_remove, NULL, 0); } -void UI_popup_handlers_add(bContext *C, ListBase *handlers, uiPopupBlockHandle *popup, const bool accept_dbl_click) +void UI_popup_handlers_add(bContext *C, ListBase *handlers, uiPopupBlockHandle *popup, const char flag) { - WM_event_add_ui_handler(C, handlers, ui_popup_handler, ui_popup_handler_remove, popup, accept_dbl_click); + WM_event_add_ui_handler(C, handlers, ui_popup_handler, ui_popup_handler_remove, popup, flag); } void UI_popup_handlers_remove(ListBase *handlers, uiPopupBlockHandle *popup) @@ -9402,8 +9872,9 @@ void UI_popup_handlers_remove_all(bContext *C, ListBase *handlers) WM_event_free_ui_handler_all(C, handlers, ui_popup_handler, ui_popup_handler_remove); } -bool UI_textbutton_activate_rna(const bContext *C, ARegion *ar, - const void *rna_poin_data, const char *rna_prop_id) +bool UI_textbutton_activate_rna( + const bContext *C, ARegion *ar, + const void *rna_poin_data, const char *rna_prop_id) { uiBlock *block; uiBut *but = NULL; diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 679681cb372..db1eacf57dc 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -55,6 +55,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_thumbs.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -888,11 +889,9 @@ int UI_icon_get_height(int icon_id) void UI_icons_init(int first_dyn_id) { -#ifdef WITH_HEADLESS - (void)first_dyn_id; -#else - init_iconfile_list(&iconfilelist); BKE_icons_init(first_dyn_id); +#ifndef WITH_HEADLESS + init_iconfile_list(&iconfilelist); init_internal_icons(); init_brush_icons(); init_matcap_icons(); @@ -904,10 +903,13 @@ void UI_icons_init(int first_dyn_id) static int preview_render_size(enum eIconSizes size) { switch (size) { - case ICON_SIZE_ICON: return 32; - case ICON_SIZE_PREVIEW: return PREVIEW_DEFAULT_HEIGHT; + case ICON_SIZE_ICON: + return ICON_RENDER_DEFAULT_HEIGHT; + case ICON_SIZE_PREVIEW: + return PREVIEW_RENDER_DEFAULT_HEIGHT; + default: + return 0; } - return 0; } /* Create rect for the icon @@ -923,12 +925,49 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size) else if (!prv_img->rect[size]) { prv_img->w[size] = render_size; prv_img->h[size] = render_size; - prv_img->changed[size] = 1; + prv_img->flag[size] |= PRV_CHANGED; prv_img->changed_timestamp[size] = 0; prv_img->rect[size] = MEM_callocN(render_size * render_size * sizeof(unsigned int), "prv_rect"); } } +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 = (DrawInfo *)icon->drawinfo; + + if (!di) { + di = icon_create_drawinfo(); + + icon->drawinfo = di; + icon->drawinfo_free = UI_icons_free_drawinfo; + } + + if (di) { + if (di->type == ICON_TYPE_PREVIEW) { + PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; + + if (prv) { + const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON; + + if (!prv->use_deferred || prv->rect[size] || (prv->flag[size] & PRV_USER_EDITED)) { + return; + } + + icon_create_rect(prv, size); + + /* Always using job (background) version. */ + ED_preview_icon_job(C, prv, NULL, prv->rect[size], prv->w[size], prv->h[size]); + + prv->flag[size] &= ~PRV_CHANGED; + } + } + } + } +} + /* only called when icon has changed */ /* only call with valid pointer from UI_icon_draw */ static void icon_set_image( @@ -940,6 +979,11 @@ static void icon_set_image( return; } + if (prv_img->flag[size] & PRV_USER_EDITED) { + /* user-edited preview, do not auto-update! */ + return; + } + icon_create_rect(prv_img, size); if (use_job) { @@ -951,7 +995,7 @@ static void icon_set_image( scene = CTX_data_scene(C); } /* Immediate version */ - ED_preview_icon_render(scene, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]); + ED_preview_icon_render(CTX_data_main(C), scene, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]); } } @@ -961,22 +1005,32 @@ PreviewImage *UI_icon_to_preview(int icon_id) if (icon) { DrawInfo *di = (DrawInfo *)icon->drawinfo; - if (di && di->data.buffer.image) { - ImBuf *bbuf; - - bbuf = IMB_ibImageFromMemory(di->data.buffer.image->datatoc_rect, di->data.buffer.image->datatoc_size, IB_rect, NULL, "<matcap buffer>"); - if (bbuf) { - PreviewImage *prv = BKE_previewimg_create(); - - prv->rect[0] = bbuf->rect; + if (di) { + if (di->type == ICON_TYPE_PREVIEW) { + PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; - prv->w[0] = bbuf->x; - prv->h[0] = bbuf->y; - - bbuf->rect = NULL; - IMB_freeImBuf(bbuf); - - return prv; + if (prv) { + return BKE_previewimg_copy(prv); + } + } + else if (di->data.buffer.image) { + ImBuf *bbuf; + + bbuf = IMB_ibImageFromMemory(di->data.buffer.image->datatoc_rect, di->data.buffer.image->datatoc_size, + IB_rect, NULL, __func__); + if (bbuf) { + PreviewImage *prv = BKE_previewimg_create(); + + prv->rect[0] = bbuf->rect; + + prv->w[0] = bbuf->x; + prv->h[0] = bbuf->y; + + bbuf->rect = NULL; + IMB_freeImBuf(bbuf); + + return prv; + } } } } @@ -987,6 +1041,10 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), unsigned int *rect, float alpha, const float rgb[3], const bool is_preview) { ImBuf *ima = NULL; + int draw_w = w; + int draw_h = h; + int draw_x = x; + int draw_y = y; /* sanity check */ if (w <= 0 || h <= 0 || w > 2000 || h > 2000) { @@ -1006,21 +1064,34 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), } /* rect contains image in 'rendersize', we only scale if needed */ - if (rw != w && rh != h) { + if (rw != w || rh != h) { + /* preserve aspect ratio and center */ + if (rw > rh) { + draw_w = w; + draw_h = (int)(((float)rh / (float)rw) * (float)w); + draw_y += (h - draw_h) / 2; + } + else if (rw < rh) { + draw_w = (int)(((float)rw / (float)rh) * (float)h); + draw_h = h; + draw_x += (w - draw_w) / 2; + } + /* if the image is squared, the draw_ initialization values are good */ + /* first allocate imbuf for scaling and copy preview into it */ ima = IMB_allocImBuf(rw, rh, 32, IB_rect); memcpy(ima->rect, rect, rw * rh * sizeof(unsigned int)); - IMB_scaleImBuf(ima, w, h); /* scale it */ + IMB_scaleImBuf(ima, draw_w, draw_h); /* scale it */ rect = ima->rect; } /* draw */ if (is_preview) { - glaDrawPixelsSafe(x, y, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glaDrawPixelsSafe(draw_x, draw_y, draw_w, draw_h, draw_w, GL_RGBA, GL_UNSIGNED_BYTE, rect); } else { - glRasterPos2f(x, y); - glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glRasterPos2f(draw_x, draw_y); + glDrawPixels(draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, rect); } if (ima) @@ -1037,8 +1108,9 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), } } -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]) +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]) { float x1, x2, y1, y2; @@ -1080,16 +1152,20 @@ static void icon_draw_texture(float x, float y, float w, float h, int ix, int iy static int get_draw_size(enum eIconSizes size) { switch (size) { - case ICON_SIZE_ICON: return ICON_DEFAULT_HEIGHT; - case ICON_SIZE_PREVIEW: return PREVIEW_DEFAULT_HEIGHT; + case ICON_SIZE_ICON: + return ICON_DEFAULT_HEIGHT; + case ICON_SIZE_PREVIEW: + return PREVIEW_DEFAULT_HEIGHT; + default: + return 0; } - return 0; } -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) +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) { bTheme *btheme = UI_GetTheme(); Icon *icon = NULL; @@ -1145,15 +1221,21 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else if (di->type == ICON_TYPE_PREVIEW) { - PreviewImage *pi = BKE_previewimg_get((ID *)icon->obj); + PreviewImage *pi = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; if (pi) { /* no create icon on this level in code */ if (!pi->rect[size]) return; /* something has gone wrong! */ /* preview images use premul alpha ... */ - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - icon_draw_rect(x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], 1.0f, NULL, is_preview); + if (GLEW_VERSION_1_4) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else { + 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, is_preview); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } } @@ -1162,17 +1244,17 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al static void ui_id_preview_image_render_size( const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job) { - if ((pi->changed[size] || !pi->rect[size])) { /* changed only ever set by dynamic icons */ + if (((pi->flag[size] & PRV_CHANGED) || !pi->rect[size])) { /* changed only ever set by dynamic icons */ /* create the rect if necessary */ icon_set_image(C, scene, id, pi, size, use_job); - pi->changed[size] = 0; + pi->flag[size] &= ~PRV_CHANGED; } } void UI_id_icon_render(const bContext *C, Scene *scene, ID *id, const bool big, const bool use_job) { - PreviewImage *pi = BKE_previewimg_get(id); + PreviewImage *pi = BKE_previewimg_id_ensure(id); if (pi) { if (big) @@ -1184,7 +1266,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) { - PreviewImage *pi = BKE_previewimg_get(id); + PreviewImage *pi = BKE_previewimg_id_ensure(id); enum eIconSizes i; if (!pi) @@ -1193,9 +1275,9 @@ static void ui_id_brush_render(const bContext *C, ID *id) for (i = 0; i < NUM_ICON_SIZES; i++) { /* check if rect needs to be created; changed * only set by dynamic icons */ - if ((pi->changed[i] || !pi->rect[i])) { + if (((pi->flag[i] & PRV_CHANGED) || !pi->rect[i])) { icon_set_image(C, NULL, id, pi, i, true); - pi->changed[i] = 0; + pi->flag[i] &= ~PRV_CHANGED; } } } @@ -1206,7 +1288,7 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id) Brush *br = (Brush *)id; if (br->flag & BRUSH_CUSTOM_ICON) { - BKE_icon_getid(id); + BKE_icon_id_ensure(id); ui_id_brush_render(C, id); } else { @@ -1268,7 +1350,7 @@ int ui_id_icon_get(const bContext *C, ID *id, const bool big) case ID_IM: /* fall through */ case ID_WO: /* fall through */ case ID_LA: /* fall through */ - iconid = BKE_icon_getid(id); + iconid = BKE_icon_id_ensure(id); /* checks if not exists, or changed */ UI_id_icon_render(C, NULL, id, big, true); break; @@ -1317,8 +1399,9 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big return rnaicon; } -static void icon_draw_at_size(float x, float y, int icon_id, float aspect, float alpha, - enum eIconSizes size, const bool nocreate) +static void icon_draw_at_size( + float x, float y, int icon_id, float aspect, float alpha, + enum eIconSizes size, const bool nocreate) { int draw_size = get_draw_size(size); icon_draw_size(x, y, icon_id, aspect, alpha, NULL, size, draw_size, nocreate, false); @@ -1356,8 +1439,8 @@ 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); } -void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, int size) +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, 1.0f, NULL, ICON_SIZE_PREVIEW, size, false, true); + icon_draw_size(x, y, icon_id, aspect, alpha, NULL, ICON_SIZE_PREVIEW, size, false, true); } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 03816a255ad..9461547a164 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -40,11 +40,9 @@ struct ARegion; struct bContext; -struct IDProperty; struct uiHandleButtonData; struct wmEvent; struct wmOperatorType; -struct wmWindow; struct wmTimer; struct uiStyle; struct uiWidgetColors; @@ -123,6 +121,14 @@ enum { /* warn: rest of uiBut->flag in UI_interface.h */ }; +/* some buttons display icons only under special conditions + * (e.g. 'x' icon in search menu) - used with ui_but_icon_extra_get */ +typedef enum uiButExtraIconType { + UI_BUT_ICONEXTRA_NONE = 1, + UI_BUT_ICONEXTRA_UNLINK, + UI_BUT_ICONEXTRA_EYEDROPPER, +} uiButExtraIconType; + /* but->pie_dir */ typedef enum RadialDirection { UI_RADIAL_NONE = -1, @@ -445,8 +451,9 @@ extern void ui_but_hsv_set(uiBut *but); extern void ui_but_v3_get(uiBut *but, float vec[3]); extern void ui_but_v3_set(uiBut *but, const float vec[3]); -extern void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect, - const float mx, const float my); +extern void ui_hsvcircle_vals_from_pos( + float *val_rad, float *val_dist, const rcti *rect, + const float mx, const float my); extern void ui_hsvcircle_pos_from_vals(struct uiBut *but, const rcti *rect, float *hsv, float *xpos, float *ypos); extern void ui_hsvcube_pos_from_vals(struct uiBut *but, const rcti *rect, float *hsv, float *xp, float *yp); bool ui_but_is_colorpicker_display_space(struct uiBut *but); @@ -459,6 +466,9 @@ extern bool ui_but_string_set_eval_num(struct bContext *C, uiBut *but, const cha extern int ui_but_string_get_max_length(uiBut *but); extern uiBut *ui_but_drag_multi_edit_get(uiBut *but); +void ui_def_but_icon(uiBut *but, const int icon, const int flag); +extern uiButExtraIconType ui_but_icon_extra_get(uiBut *but); + extern void ui_but_default_set(struct bContext *C, const bool all, const bool use_afterfunc); extern void ui_but_update(uiBut *but); @@ -468,7 +478,6 @@ extern bool ui_but_is_unit(const uiBut *but) ATTR_WARN_UNUSED_RESULT; extern bool ui_but_is_compatible(const uiBut *but_a, const uiBut *but_b) ATTR_WARN_UNUSED_RESULT; extern bool ui_but_is_rna_valid(uiBut *but) ATTR_WARN_UNUSED_RESULT; extern bool ui_but_is_utf8(const uiBut *but) ATTR_WARN_UNUSED_RESULT; -extern bool ui_but_is_search_unlink_visible(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; @@ -575,20 +584,22 @@ bool ui_searchbox_apply(uiBut *but, struct ARegion *ar); void ui_searchbox_free(struct bContext *C, struct ARegion *ar); void ui_but_search_refresh(uiBut *but); -uiBlock *ui_popup_block_refresh(struct bContext *C, uiPopupBlockHandle *handle, - ARegion *butregion, uiBut *but); +uiBlock *ui_popup_block_refresh( + struct bContext *C, uiPopupBlockHandle *handle, + ARegion *butregion, uiBut *but); -uiPopupBlockHandle *ui_popup_block_create(struct bContext *C, struct ARegion *butregion, uiBut *but, - uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, - void *arg); -uiPopupBlockHandle *ui_popup_menu_create(struct bContext *C, struct ARegion *butregion, uiBut *but, - uiMenuCreateFunc create_func, void *arg); +uiPopupBlockHandle *ui_popup_block_create( + struct bContext *C, struct ARegion *butregion, uiBut *but, + uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, + void *arg); +uiPopupBlockHandle *ui_popup_menu_create( + struct bContext *C, struct ARegion *butregion, uiBut *but, + uiMenuCreateFunc create_func, void *arg); void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle); int ui_but_menu_step(uiBut *but, int step); -struct AutoComplete; /* interface_panel.c */ extern int ui_handler_panel_region(struct bContext *C, const struct wmEvent *event, struct ARegion *ar); @@ -635,7 +646,7 @@ uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new); #ifdef WITH_INPUT_IME void ui_but_ime_reposition(uiBut *but, int x, int y, bool complete); -struct wmIMEData *ui_but_get_ime_data(uiBut *but); +struct wmIMEData *ui_but_ime_data_get(uiBut *but); #endif /* interface_widgets.c */ @@ -664,6 +675,7 @@ void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, const char *na void uiStyleInit(void); /* interface_icons.c */ +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); /* resources.c */ diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 44c1ed474d5..a61b208278d 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -356,9 +356,10 @@ static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index) } /* create buttons for an item with an RNA array */ -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) +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) { uiStyle *style = layout->root->style; uiBut *but; @@ -545,8 +546,9 @@ static void ui_item_enum_expand_handle(bContext *C, void *arg1, void *arg2) RNA_property_enum_set(&but->rnapoin, but->rnaprop, current_value); } } -static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, - const char *uiname, int h, bool icon_only) +static void ui_item_enum_expand( + uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, + const char *uiname, int h, bool icon_only) { /* XXX The way this function currently handles uiname parameter is insane and inconsistent with general UI API: * * uiname is the *enum property* label. @@ -681,14 +683,17 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n return but; } -void UI_context_active_but_prop_get_filebrowser(const bContext *C, PointerRNA *ptr, PropertyRNA **prop) +void UI_context_active_but_prop_get_filebrowser( + const bContext *C, + PointerRNA *r_ptr, PropertyRNA **r_prop, bool *r_is_undo) { ARegion *ar = CTX_wm_region(C); uiBlock *block; uiBut *but, *prevbut; - memset(ptr, 0, sizeof(*ptr)); - *prop = NULL; + memset(r_ptr, 0, sizeof(*r_ptr)); + *r_prop = NULL; + *r_is_undo = false; if (!ar) return; @@ -700,8 +705,9 @@ void UI_context_active_but_prop_get_filebrowser(const bContext *C, PointerRNA *p /* find the button before the active one */ if ((but->flag & UI_BUT_LAST_ACTIVE) && prevbut && prevbut->rnapoin.data) { if (RNA_property_type(prevbut->rnaprop) == PROP_STRING) { - *ptr = prevbut->rnapoin; - *prop = prevbut->rnaprop; + *r_ptr = prevbut->rnapoin; + *r_prop = prevbut->rnaprop; + *r_is_undo = (prevbut->flag & UI_BUT_UNDO) != 0; return; } } @@ -877,8 +883,9 @@ void uiItemEnumO(uiLayout *layout, const char *opname, const char *name, int ico } -void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname, IDProperty *properties, - int context, int flag) +void uiItemsFullEnumO( + uiLayout *layout, const char *opname, const char *propname, IDProperty *properties, + int context, int flag) { wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */ @@ -1129,8 +1136,9 @@ 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) +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) { PropertyType type; PropertySubType subtype; @@ -1573,11 +1581,14 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN /* turn button into search button */ if (searchprop) { - but->type = RNA_property_is_unlink(prop) ? UI_BTYPE_SEARCH_MENU_UNLINK : UI_BTYPE_SEARCH_MENU; + but->type = UI_BTYPE_SEARCH_MENU; but->hardmax = MAX2(but->hardmax, 256.0f); but->rnasearchpoin = *searchptr; but->rnasearchprop = searchprop; but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT; + if (RNA_property_is_unlink(prop)) { + but->flag |= UI_BUT_SEARCH_UNLINK; + } if (RNA_property_type(prop) == PROP_ENUM) { /* XXX, this will have a menu string, @@ -1677,8 +1688,9 @@ static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt) 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) +static uiBut *ui_item_menu( + uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN, + const char *tip, bool force_menu) { uiBlock *block = layout->root->block; uiBut *but; @@ -2139,7 +2151,11 @@ static void ui_litem_layout_column(uiLayout *litem) static RadialDirection ui_get_radialbut_vec(float vec[2], short itemnum) { RadialDirection dir; - BLI_assert(itemnum < 8); + + if (itemnum >= 8) { + itemnum %= 8; + printf("Warning: Pie menus with more than 8 items are currently unsupported\n"); + } dir = ui_radial_dir_order[itemnum]; ui_but_pie_dir(dir, vec); @@ -2717,7 +2733,8 @@ uiLayout *uiLayoutBox(uiLayout *layout) return (uiLayout *)ui_layout_box(layout, UI_BTYPE_ROUNDBOX); } -/* Check all buttons defined in this layout, and set any button flagged as UI_BUT_LIST_ITEM as active/selected. +/** + * Check all buttons defined in this layout, and set any button flagged as UI_BUT_LIST_ITEM as active/selected. * Needed to handle correctly text colors of active (selected) list item. */ void ui_layout_list_set_labels_active(uiLayout *layout) @@ -2733,8 +2750,9 @@ void ui_layout_list_set_labels_active(uiLayout *layout) } } -uiLayout *uiLayoutListBox(uiLayout *layout, uiList *ui_list, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr, - PropertyRNA *actprop) +uiLayout *uiLayoutListBox( + uiLayout *layout, uiList *ui_list, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr, + PropertyRNA *actprop) { uiLayoutItemBx *box = ui_layout_box(layout, UI_BTYPE_LISTBOX); uiBut *but = box->roundbox; @@ -3333,9 +3351,10 @@ static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), void *op_pt, #endif /* this function does not initialize the layout, functions can be called on the layout before and after */ -void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, - bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *), - const char label_align, const short flag) +void uiLayoutOperatorButs( + const bContext *C, uiLayout *layout, wmOperator *op, + bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *), + const char label_align, const short flag) { if (!op->properties) { IDPropertyTemplate val = {0}; diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 41d2a90e548..23b20591275 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -33,6 +33,7 @@ #include "DNA_screen_types.h" #include "DNA_text_types.h" /* for UI_OT_reports_to_text */ +#include "DNA_object_types.h" /* for OB_DATA_SUPPORT_ID */ #include "BLI_blenlib.h" #include "BLI_math_color.h" @@ -43,6 +44,7 @@ #include "BKE_context.h" #include "BKE_screen.h" #include "BKE_global.h" +#include "BKE_node.h" #include "BKE_text.h" /* for UI_OT_reports_to_text */ #include "BKE_report.h" @@ -261,7 +263,7 @@ static void UI_OT_unset_property_button(wmOperatorType *ot) /* Copy To Selected Operator ------------------------ */ -static bool copy_to_selected_list( +bool UI_context_copy_to_selected_list( bContext *C, PointerRNA *ptr, PropertyRNA *prop, ListBase *r_lb, bool *r_use_path_from_id, char **r_path) { @@ -277,6 +279,49 @@ static bool copy_to_selected_list( else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) { *r_lb = CTX_data_collection_get(C, "selected_editable_sequences"); } + else if (RNA_struct_is_a(ptr->type, &RNA_Node) || + RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) + { + ListBase lb = {NULL, NULL}; + char *path = NULL; + bNode *node = NULL; + + /* Get the node we're editing */ + if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) { + bNodeTree *ntree = ptr->id.data; + bNodeSocket *sock = ptr->data; + if (nodeFindNode(ntree, sock, &node, NULL)) { + if ((path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != NULL) { + /* we're good! */ + } + else { + node = NULL; + } + } + } + else { + node = ptr->data; + } + + /* Now filter by type */ + if (node) { + CollectionPointerLink *link, *link_next; + lb = CTX_data_collection_get(C, "selected_nodes"); + + for (link = lb.first; link; link = link_next) { + bNode *node_data = link->ptr.data; + link_next = link->next; + + if (node_data->type != node->type) { + BLI_remlink(&lb, link); + MEM_freeN(link); + } + } + } + + *r_lb = lb; + *r_path = path; + } else if (ptr->id.data) { ID *id = ptr->id.data; @@ -285,6 +330,51 @@ static bool copy_to_selected_list( *r_use_path_from_id = true; *r_path = RNA_path_from_ID_to_property(ptr, prop); } + else if (OB_DATA_SUPPORT_ID(GS(id->name))) { + /* check we're using the active object */ + const short id_code = GS(id->name); + ListBase lb = CTX_data_collection_get(C, "selected_editable_objects"); + char *path = RNA_path_from_ID_to_property(ptr, prop); + + /* de-duplicate obdata */ + if (!BLI_listbase_is_empty(&lb)) { + CollectionPointerLink *link, *link_next; + + for (link = lb.first; link; link = link->next) { + Object *ob = link->ptr.id.data; + if (ob->data) { + ID *id_data = ob->data; + id_data->flag |= LIB_DOIT; + } + } + + for (link = lb.first; link; link = link_next) { + Object *ob = link->ptr.id.data; + ID *id_data = ob->data; + link_next = link->next; + + if ((id_data == NULL) || + (id_data->flag & LIB_DOIT) == 0 || + (id_data->lib) || + (GS(id_data->name) != id_code)) + { + BLI_remlink(&lb, link); + MEM_freeN(link); + } + else { + /* avoid prepending 'data' to the path */ + RNA_id_pointer_create(id_data, &link->ptr); + } + + if (id_data) { + id_data->flag &= ~LIB_DOIT; + } + } + } + + *r_lb = lb; + *r_path = path; + } else if (GS(id->name) == ID_SCE) { /* Sequencer's ID is scene :/ */ /* Try to recursively find an RNA_Sequence ancestor, to handle situations like T41062... */ @@ -325,7 +415,7 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll) CollectionPointerLink *link; ListBase lb; - if (!copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path)) + if (!UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path)) return success; for (link = lb.first; link; link = link->next) { @@ -553,8 +643,9 @@ void UI_editsource_active_but_test(uiBut *but) BLI_ghash_insert(ui_editsource_info->hash, but, but_store); } -static int editsource_text_edit(bContext *C, wmOperator *op, - char filepath[FILE_MAX], int line) +static int editsource_text_edit( + bContext *C, wmOperator *op, + char filepath[FILE_MAX], int line) { struct Main *bmain = CTX_data_main(C); Text *text; @@ -613,6 +704,7 @@ static int editsource_exec(bContext *C, wmOperator *op) /* redraw and get active button python info */ ED_region_do_draw(C, ar); + ar->do_draw = false; for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash); BLI_ghashIterator_done(&ghi) == false; @@ -667,10 +759,12 @@ static void UI_OT_editsource(wmOperatorType *ot) } /* ------------------------------------------------------------------------- */ -/* EditTranslation utility funcs and operator, - * Note: this includes utility functions and button matching checks. - * this only works in conjunction with a py operator! */ +/** + * EditTranslation utility funcs and operator, + * \note: this includes utility functions and button matching checks. + * this only works in conjunction with a py operator! + */ static void edittranslation_find_po_file(const char *root, const char *uilng, char *path, const size_t maxlen) { char tstr[32]; /* Should be more than enough! */ diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index d165e2719c5..665266edb9f 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -82,6 +82,14 @@ /* only show pin header button for pinned panels */ #define USE_PIN_HIDDEN +/* the state of the mouse position relative to the panel */ +typedef enum uiPanelMouseState { + PANEL_MOUSE_OUTSIDE, /* mouse is not in the panel */ + PANEL_MOUSE_INSIDE_CONTENT, /* mouse is in the actual panel content */ + PANEL_MOUSE_INSIDE_HEADER, /* mouse is in the panel header */ + PANEL_MOUSE_INSIDE_SCALE, /* mouse is inside panel scale widget */ +} uiPanelMouseState; + typedef enum uiHandlePanelState { PANEL_STATE_DRAG, PANEL_STATE_DRAG_SCALE, @@ -202,8 +210,9 @@ static void ui_panel_copy_offset(Panel *pa, Panel *papar) } -/* XXX Disabled paneltab handling for now. Old 2.4x feature, *DO NOT* confuse it with new tool tabs in 2.70. ;) - * See also T41704. +/** + * XXX Disabled paneltab handling for now. Old 2.4x feature, *DO NOT* confuse it with new tool tabs in 2.70. ;) + * See also T41704. */ /* #define UI_USE_PANELTAB */ @@ -560,6 +569,8 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con rcti headrect; rctf itemrect; int ofsx; + const bool is_closed_x = (panel->flag & PNL_CLOSEDX) ? true : false; + const bool is_closed_y = (panel->flag & PNL_CLOSEDY) ? true : false; if (panel->paneltab) return; if (panel->type && (panel->type->flag & PNL_NO_HEADER)) return; @@ -572,7 +583,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con { float minx = rect->xmin; - float maxx = rect->xmax; + float maxx = is_closed_x ? (minx + PNL_HEADER / block->aspect) : rect->xmax; float y = headrect.ymax; glEnable(GL_BLEND); @@ -587,8 +598,11 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con } else if (!(panel->runtime_flag & PNL_FIRST)) { /* draw embossed separator */ - minx += 5.0f / block->aspect; - maxx -= 5.0f / block->aspect; + + if (is_closed_x == false) { + minx += 5.0f / block->aspect; + maxx -= 5.0f / block->aspect; + } glColor4f(0.0f, 0.0f, 0.0f, 0.5f); fdrawline(minx, y, maxx, y); @@ -615,7 +629,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con } /* horizontal title */ - if (!(panel->flag & PNL_CLOSEDX)) { + if (is_closed_x == false) { ui_draw_aligned_panel_header(style, block, &headrect, 'h'); /* itemrect smaller */ @@ -631,9 +645,10 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con /* if the panel is minimized vertically: * (------) */ - if (panel->flag & PNL_CLOSEDY) { + if (is_closed_y) { + /* skip */ } - else if (panel->flag & PNL_CLOSEDX) { + else if (is_closed_x) { /* draw vertical title */ ui_draw_aligned_panel_header(style, block, &headrect, 'v'); } @@ -680,9 +695,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con BLI_rctf_scale(&itemrect, 0.35f); - if (panel->flag & PNL_CLOSEDY) + if (is_closed_y) ui_draw_tria_rect(&itemrect, 'h'); - else if (panel->flag & PNL_CLOSEDX) + else if (is_closed_x) ui_draw_tria_rect(&itemrect, 'h'); else ui_draw_tria_rect(&itemrect, 'v'); @@ -729,11 +744,13 @@ typedef struct PanelSort { Panel *pa, *orig; } PanelSort; -/* note about sorting; +/** + * \note about sorting; * the sortorder has a lower value for new panels being added. * however, that only works to insert a single panel, when more new panels get * added the coordinates of existing panels and the previously stored to-be-inserted - * panels do not match for sorting */ + * panels do not match for sorting + */ static int find_leftmost_panel(const void *a1, const void *a2) { @@ -1128,6 +1145,157 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel) /******************* region level panel interaction *****************/ +static uiPanelMouseState ui_panel_mouse_state_get(const uiBlock *block, const Panel *pa, const int mx, const int my) +{ + /* open panel */ + if (pa->flag & PNL_CLOSEDX) { + if ((block->rect.xmin <= mx) && (block->rect.xmin + PNL_HEADER >= mx)) { + return PANEL_MOUSE_INSIDE_HEADER; + } + } + /* outside left/right side */ + else if ((block->rect.xmin > mx) || (block->rect.xmax < mx)) { + /* pass */ + } + else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) { + return PANEL_MOUSE_INSIDE_HEADER; + } + /* open panel */ + else if (!(pa->flag & PNL_CLOSEDY)) { + if (pa->control & UI_PNL_SCALE) { + if (block->rect.xmax - PNL_HEADER <= mx) { + if (block->rect.ymin + PNL_HEADER >= my) { + return PANEL_MOUSE_INSIDE_SCALE; + } + } + } + if ((block->rect.xmin <= mx) && (block->rect.xmax >= mx)) { + if ((block->rect.ymin <= my) && (block->rect.ymax + PNL_HEADER >= my)) { + return PANEL_MOUSE_INSIDE_CONTENT; + } + } + } + return PANEL_MOUSE_OUTSIDE; +} + +typedef struct uiPanelDragCollapseHandle { + bool was_first_open; + int xy_init[2]; +} uiPanelDragCollapseHandle; + +static void ui_panel_drag_collapse_handler_remove(bContext *UNUSED(C), void *userdata) +{ + uiPanelDragCollapseHandle *dragcol_data = userdata; + MEM_freeN(dragcol_data); +} + +static void ui_panel_drag_collapse(bContext *C, uiPanelDragCollapseHandle *dragcol_data, const int xy_dst[2]) +{ + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + uiBlock *block; + Panel *pa; + + for (block = ar->uiblocks.first; block; block = block->next) { + float xy_a_block[2] = {UNPACK2(dragcol_data->xy_init)}; + float xy_b_block[2] = {UNPACK2(xy_dst)}; + rctf rect = block->rect; + int oldflag; + const bool is_horizontal = (panel_aligned(sa, ar) == BUT_HORIZONTAL); + + if ((pa = block->panel) == 0 || (pa->type && (pa->type->flag & PNL_NO_HEADER))) { + continue; + } + oldflag = pa->flag; + + /* lock one axis */ + if (is_horizontal) { + xy_b_block[1] = dragcol_data->xy_init[1]; + } + else { + xy_b_block[0] = dragcol_data->xy_init[0]; + } + + /* use cursor coords in block space */ + ui_window_to_block_fl(ar, block, &xy_a_block[0], &xy_a_block[1]); + ui_window_to_block_fl(ar, block, &xy_b_block[0], &xy_b_block[1]); + + /* set up rect to match header size */ + rect.ymin = rect.ymax; + rect.ymax = rect.ymin + PNL_HEADER; + if (pa->flag & PNL_CLOSEDX) { + rect.xmax = rect.xmin + PNL_HEADER; + } + + /* touch all panels between last mouse coord and the current one */ + if (BLI_rctf_isect_segment(&rect, xy_a_block, xy_b_block)) { + /* force panel to close */ + if (dragcol_data->was_first_open == true) { + pa->flag |= (is_horizontal ? PNL_CLOSEDX : PNL_CLOSEDY); + } + /* force panel to open */ + else { + pa->flag &= ~PNL_CLOSED; + } + + /* if pa->flag has changed this means a panel was opened/closed here */ + if (pa->flag != oldflag) { + panel_activate_state(C, pa, PANEL_STATE_ANIMATION); + } + } + } +} + +/** + * Panel drag-collapse (modal handler) + * Clicking and dragging over panels toggles their collapse state based on the panel that was first + * dragged over. If it was open all affected panels incl the initial one are closed and vise versa. + */ +static int ui_panel_drag_collapse_handler(bContext *C, const wmEvent *event, void *userdata) +{ + wmWindow *win = CTX_wm_window(C); + uiPanelDragCollapseHandle *dragcol_data = userdata; + short retval = WM_UI_HANDLER_CONTINUE; + + switch (event->type) { + case MOUSEMOVE: + ui_panel_drag_collapse(C, dragcol_data, &event->x); + + retval = WM_UI_HANDLER_BREAK; + break; + case LEFTMOUSE: + if (event->val == KM_RELEASE) { + /* done! */ + WM_event_remove_ui_handler( + &win->modalhandlers, + ui_panel_drag_collapse_handler, + ui_panel_drag_collapse_handler_remove, + dragcol_data, true); + ui_panel_drag_collapse_handler_remove(C, dragcol_data); + } + /* don't let any left-mouse event fall through! */ + retval = WM_UI_HANDLER_BREAK; + break; + } + + return retval; +} + +static void ui_panel_drag_collapse_handler_add(const bContext *C, const bool was_open) +{ + wmWindow *win = CTX_wm_window(C); + wmEvent *event = win->eventstate; + uiPanelDragCollapseHandle *dragcol_data = MEM_mallocN(sizeof(*dragcol_data), __func__); + + dragcol_data->was_first_open = was_open; + copy_v2_v2_int(dragcol_data->xy_init, &event->x); + + WM_event_add_ui_handler( + C, &win->modalhandlers, + ui_panel_drag_collapse_handler, + ui_panel_drag_collapse_handler_remove, + dragcol_data, 0); +} /* this function is supposed to call general window drawing too */ /* also it supposes a block has panel, and isn't a menu */ @@ -1187,23 +1355,39 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in ED_region_tag_redraw(ar); } else { /* collapse */ - if (ctrl) + if (ctrl) { panels_collapse_all(sa, ar, block->panel); + /* reset the view - we don't want to display a view without content */ + UI_view2d_offset(&ar->v2d, 0.0f, 1.0f); + } + if (block->panel->flag & PNL_CLOSED) { block->panel->flag &= ~PNL_CLOSED; /* snap back up so full panel aligns with screen edge */ if (block->panel->snap & PNL_SNAP_BOTTOM) block->panel->ofsy = 0; + + if (event == LEFTMOUSE) { + ui_panel_drag_collapse_handler_add(C, false); + } } else if (align == BUT_HORIZONTAL) { block->panel->flag |= PNL_CLOSEDX; + + if (event == LEFTMOUSE) { + ui_panel_drag_collapse_handler_add(C, true); + } } else { - /* snap down to bottom screen edge*/ + /* snap down to bottom screen edge */ block->panel->flag |= PNL_CLOSEDY; if (block->panel->snap & PNL_SNAP_BOTTOM) block->panel->ofsy = -block->panel->sizey; + + if (event == LEFTMOUSE) { + ui_panel_drag_collapse_handler_add(C, true); + } } for (pa = ar->panels.first; pa; pa = pa->next) { @@ -1332,10 +1516,11 @@ void UI_panel_category_clear_all(ARegion *ar) } /* based on UI_draw_roundbox_gl_mode, 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, - int roundboxtype, - const bool use_highlight, const bool use_shadow, - const unsigned char highlight_fade[3]) +static void ui_panel_category_draw_tab( + int mode, 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]) { float vec[4][2] = { {0.195, 0.02}, @@ -1718,8 +1903,8 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) } for (block = ar->uiblocks.last; block; block = block->prev) { - bool inside = false, inside_header = false, inside_scale = false; - + uiPanelMouseState mouse_state; + mx = event->x; my = event->y; ui_window_to_block(ar, block, &mx, &my); @@ -1731,32 +1916,11 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) continue; if (pa->type && pa->type->flag & PNL_NO_HEADER) /* XXX - accessed freed panels when scripts reload, need to fix. */ continue; - - /* clicked at panel header? */ - if (pa->flag & PNL_CLOSEDX) { - if (block->rect.xmin <= mx && block->rect.xmin + PNL_HEADER >= mx) - inside_header = true; - } - else if (block->rect.xmin > mx || block->rect.xmax < mx) { - /* outside left/right side */ - } - else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) { - inside_header = true; - } - else if (!(pa->flag & PNL_CLOSEDY)) { - /* open panel */ - if (pa->control & UI_PNL_SCALE) { - if (block->rect.xmax - PNL_HEADER <= mx) - if (block->rect.ymin + PNL_HEADER >= my) - inside_scale = true; - } - if (block->rect.xmin <= mx && block->rect.xmax >= mx) - if (block->rect.ymin <= my && block->rect.ymax + PNL_HEADER >= my) - inside = true; - } - + + mouse_state = ui_panel_mouse_state_get(block, pa, mx, my); + /* XXX hardcoded key warning */ - if ((inside || inside_header) && event->val == KM_PRESS) { + if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER) && event->val == KM_PRESS) { if (event->type == AKEY && ((event->ctrl + event->oskey + event->shift + event->alt) == 0)) { if (pa->flag & PNL_CLOSEDY) { @@ -1775,13 +1939,13 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) if (ui_but_is_active(ar)) continue; - if (inside || inside_header) { + if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) { if (event->val == KM_PRESS) { /* open close on header */ if (ELEM(event->type, RETKEY, PADENTER)) { - if (inside_header) { + if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { ui_handle_panel_header(C, block, mx, my, RETKEY, event->ctrl, event->shift); retval = WM_UI_HANDLER_BREAK; break; @@ -1791,12 +1955,12 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) /* all inside clicks should return in break - overlapping/float panels */ retval = WM_UI_HANDLER_BREAK; - if (inside_header) { - ui_handle_panel_header(C, block, mx, my, 0, event->ctrl, event->shift); + if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { + ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->shift); retval = WM_UI_HANDLER_BREAK; break; } - else if (inside_scale && !(pa->flag & PNL_CLOSED)) { + else if ((mouse_state == PANEL_MOUSE_INSIDE_SCALE) && !(pa->flag & PNL_CLOSED)) { panel_activate_state(C, pa, PANEL_STATE_DRAG_SCALE); retval = WM_UI_HANDLER_BREAK; break; @@ -1804,7 +1968,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) } else if (event->type == RIGHTMOUSE) { - if (inside_header) { + if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { ui_panel_menu(C, ar, block->panel); retval = WM_UI_HANDLER_BREAK; break; @@ -1943,7 +2107,7 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat data = MEM_callocN(sizeof(uiHandlePanelData), "uiHandlePanelData"); pa->activedata = data; - WM_event_add_ui_handler(C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, false); + WM_event_add_ui_handler(C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, 0); } if (ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG)) diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 6e5f6af3c5f..6aabbbe76b6 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -70,8 +70,9 @@ #include "interface_intern.h" -#define MENU_TOP 8 +#define MENU_TOP (int)(8 * UI_DPI_FAC) #define MENU_PADDING (int)(0.2f * UI_UNIT_Y) +#define MENU_BORDER (int)(0.3f * U.widget_unit) static int rna_property_enum_step(const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int direction) { @@ -179,9 +180,10 @@ typedef struct uiTooltipData { BLI_STATIC_ASSERT(UI_TIP_LC_MAX == UI_TIP_LC_ALERT + 1, "invalid lc-max"); BLI_STATIC_ASSERT(sizeof(((uiTooltipData *)NULL)->format[0]) <= sizeof(int), "oversize"); -static void rgb_tint(float col[3], - float h, float h_strength, - float v, float v_strength) +static void rgb_tint( + float col[3], + float h, float h_strength, + float v, float v_strength) { float col_hsv_from[3]; float col_hsv_to[3]; @@ -241,10 +243,10 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) /* tone_fg = rgb_to_grayscale(main_color); */ /* mix the colors */ - rgb_tint(value_color, 0.0f, 0.0f, tone_bg, 0.2f); /* light grey */ + rgb_tint(value_color, 0.0f, 0.0f, tone_bg, 0.2f); /* light gray */ rgb_tint(active_color, 0.6f, 0.2f, tone_bg, 0.2f); /* light blue */ - rgb_tint(normal_color, 0.0f, 0.0f, tone_bg, 0.4f); /* grey */ - rgb_tint(python_color, 0.0f, 0.0f, tone_bg, 0.5f); /* dark grey */ + rgb_tint(normal_color, 0.0f, 0.0f, tone_bg, 0.4f); /* gray */ + rgb_tint(python_color, 0.0f, 0.0f, tone_bg, 0.5f); /* dark gray */ rgb_tint(alert_color, 0.0f, 0.8f, tone_bg, 0.1f); /* red */ /* draw text */ @@ -261,7 +263,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) /* override text-style */ fstyle_header.shadow = 1; - fstyle_header.shadowcolor = rgb_to_luma(tip_colors[UI_TIP_LC_MAIN]); + fstyle_header.shadowcolor = rgb_to_grayscale(tip_colors[UI_TIP_LC_MAIN]); fstyle_header.shadx = fstyle_header.shady = 0; fstyle_header.shadowalpha = 1.0f; @@ -394,7 +396,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) data->totline++; } - if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) { + if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { /* better not show the value of a password */ if ((but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD)) == 0) { /* full string */ @@ -815,7 +817,7 @@ static void ui_searchbox_select(bContext *C, ARegion *ar, uiBut *but, int step) } else { /* only let users step into an 'unset' state for unlink buttons */ - data->active = (but->type == UI_BTYPE_SEARCH_MENU_UNLINK) ? -1 : 0; + data->active = (but->flag & UI_BUT_SEARCH_UNLINK) ? -1 : 0; } } @@ -826,8 +828,8 @@ static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr { /* thumbnail preview */ if (data->preview) { - int butw = BLI_rcti_size_x(&data->bbox) / data->prv_cols; - int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_TOP) / data->prv_rows; + int butw = (BLI_rcti_size_x(&data->bbox) - 2 * MENU_BORDER) / data->prv_cols; + int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_BORDER) / data->prv_rows; int row, col; *r_rect = data->bbox; @@ -835,10 +837,10 @@ static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr col = itemnr % data->prv_cols; row = itemnr / data->prv_cols; - r_rect->xmin += col * butw; + r_rect->xmin += MENU_BORDER + (col * butw); r_rect->xmax = r_rect->xmin + butw; - r_rect->ymax = data->bbox.ymax - MENU_TOP - (row * buth); + r_rect->ymax -= MENU_BORDER + (row * buth); r_rect->ymin = r_rect->ymax - buth; } /* list view */ @@ -886,7 +888,7 @@ bool ui_searchbox_apply(uiBut *but, ARegion *ar) return true; } - else if (but->type == UI_BTYPE_SEARCH_MENU_UNLINK) { + else if (but->flag & UI_BUT_SEARCH_UNLINK) { /* It is valid for _UNLINK flavor to have no active element (it's a valid way to unlink). */ but->editstr[0] = '\0'; @@ -1044,14 +1046,8 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) ui_searchbox_butrect(&rect, data, a); /* widget itself */ - if (data->preview) { - ui_draw_preview_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], - (a == data->active) ? UI_ACTIVE : 0); - } - else { - ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], - (a == data->active) ? UI_ACTIVE : 0, data->use_sep); - } + ui_draw_preview_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], + (a == data->active) ? UI_ACTIVE : 0); } /* indicate more */ @@ -1164,25 +1160,27 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) /* compute position */ if (but->block->flag & UI_BLOCK_SEARCH_MENU) { - const int margin = UI_POPUP_MARGIN; + const int margin_x = UI_POPUP_MARGIN; + const int margin_y = MENU_TOP; + const int search_but_h = BLI_rctf_size_y(&but->rect) + 10; /* this case is search menu inside other menu */ /* we copy region size */ ar->winrct = butregion->winrct; /* widget rect, in region coords */ - data->bbox.xmin = margin; - data->bbox.xmax = BLI_rcti_size_x(&ar->winrct) - margin; + data->bbox.xmin = margin_x; + data->bbox.xmax = BLI_rcti_size_x(&ar->winrct) - margin_x; /* Do not use shadow width for height, gives insane margin with big shadows, and issue T41548 with small ones */ - data->bbox.ymin = 8 * UI_DPI_FAC; - data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - 8 * UI_DPI_FAC; + data->bbox.ymin = margin_y; + data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - margin_y; /* check if button is lower half */ if (but->rect.ymax < BLI_rctf_cent_y(&but->block->rect)) { - data->bbox.ymin += BLI_rctf_size_y(&but->rect); + data->bbox.ymin += search_but_h; } else { - data->bbox.ymax -= BLI_rctf_size_y(&but->rect); + data->bbox.ymax -= search_but_h; } } else { @@ -1426,7 +1424,8 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, if (down || top) { if (dir1 == UI_DIR_UP && top == 0) dir1 = UI_DIR_DOWN; if (dir1 == UI_DIR_DOWN && down == 0) dir1 = UI_DIR_UP; - if (dir2 == UI_DIR_UP && top == 0) dir2 = UI_DIR_DOWN; + BLI_assert(dir2 != UI_DIR_UP); +// if (dir2 == UI_DIR_UP && top == 0) dir2 = UI_DIR_DOWN; if (dir2 == UI_DIR_DOWN && down == 0) dir2 = UI_DIR_UP; } @@ -1638,7 +1637,7 @@ static void ui_popup_block_remove(bContext *C, uiPopupBlockHandle *handle) } /** - * Called for creatign new popups and refreshing existing ones. + * Called for creating new popups and refreshing existing ones. */ uiBlock *ui_popup_block_refresh( bContext *C, uiPopupBlockHandle *handle, @@ -1684,13 +1683,8 @@ uiBlock *ui_popup_block_refresh( ar->regiondata = handle; /* set UI_BLOCK_NUMSELECT before UI_block_end() so we get alphanumeric keys assigned */ - if (but) { - if (but->type == UI_BTYPE_PULLDOWN) { - block->flag |= UI_BLOCK_NUMSELECT; - } - } - else { - block->flag |= UI_BLOCK_POPUP | UI_BLOCK_NUMSELECT; + if (but == NULL) { + block->flag |= UI_BLOCK_POPUP; } block->flag |= UI_BLOCK_LOOP; @@ -1808,9 +1802,10 @@ uiBlock *ui_popup_block_refresh( return block; } -uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut *but, - uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, - void *arg) +uiPopupBlockHandle *ui_popup_block_create( + bContext *C, ARegion *butregion, uiBut *but, + uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, + void *arg) { wmWindow *window = CTX_wm_window(C); static ARegionType type; @@ -2571,8 +2566,9 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi return pup->block; } -uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut *but, - uiMenuCreateFunc menu_func, void *arg) +uiPopupBlockHandle *ui_popup_menu_create( + bContext *C, ARegion *butregion, uiBut *but, + uiMenuCreateFunc menu_func, void *arg) { wmWindow *window = CTX_wm_window(C); uiStyle *style = UI_style_get_dpi(); @@ -2619,7 +2615,7 @@ uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut if (!but) { handle->popup = true; - UI_popup_handlers_add(C, &window->modalhandlers, handle, false); + UI_popup_handlers_add(C, &window->modalhandlers, handle, 0); WM_event_add_mousemove(C); } @@ -2681,7 +2677,7 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup) menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPUP, pup); menu->popup = true; - UI_popup_handlers_add(C, &window->modalhandlers, menu, false); + UI_popup_handlers_add(C, &window->modalhandlers, menu, 0); WM_event_add_mousemove(C); MEM_freeN(pup); @@ -2807,7 +2803,9 @@ void UI_pie_menu_end(bContext *C, uiPieMenu *pie) menu->popup = true; menu->towardstime = PIL_check_seconds_timer(); - UI_popup_handlers_add(C, &window->modalhandlers, menu, true); + UI_popup_handlers_add( + C, &window->modalhandlers, + menu, WM_HANDLER_ACCEPT_DBL_CLICK); WM_event_add_mousemove(C); MEM_freeN(pie); @@ -2850,8 +2848,9 @@ int UI_pie_menu_invoke(struct bContext *C, const char *idname, const wmEvent *ev return OPERATOR_INTERFACE; } -int UI_pie_menu_invoke_from_operator_enum(struct bContext *C, const char *title, const char *opname, - const char *propname, const wmEvent *event) +int UI_pie_menu_invoke_from_operator_enum( + struct bContext *C, const char *title, const char *opname, + const char *propname, const wmEvent *event) { uiPieMenu *pie; uiLayout *layout; @@ -2867,8 +2866,9 @@ int UI_pie_menu_invoke_from_operator_enum(struct bContext *C, const char *title, return OPERATOR_INTERFACE; } -int UI_pie_menu_invoke_from_rna_enum(struct bContext *C, const char *title, const char *path, - const wmEvent *event) +int UI_pie_menu_invoke_from_rna_enum( + struct bContext *C, const char *title, const char *path, + const wmEvent *event) { PointerRNA ctx_ptr; PointerRNA r_ptr; @@ -2997,7 +2997,7 @@ void UI_popup_block_invoke_ex(bContext *C, uiBlockCreateFunc func, void *arg, co handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL; handle->opcontext = opcontext; - UI_popup_handlers_add(C, &window->modalhandlers, handle, false); + UI_popup_handlers_add(C, &window->modalhandlers, handle, 0); WM_event_add_mousemove(C); } @@ -3020,7 +3020,7 @@ void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc po handle->cancel_func = cancel_func; // handle->opcontext = opcontext; - UI_popup_handlers_add(C, &window->modalhandlers, handle, false); + UI_popup_handlers_add(C, &window->modalhandlers, handle, 0); WM_event_add_mousemove(C); } @@ -3039,17 +3039,15 @@ void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, int handle->cancel_func = confirm_cancel_operator; handle->opcontext = opcontext; - UI_popup_handlers_add(C, &window->modalhandlers, handle); + UI_popup_handlers_add(C, &window->modalhandlers, handle, 0); WM_event_add_mousemove(C); } #endif -void UI_popup_block_close(bContext *C, uiBlock *block) +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) { - wmWindow *win = CTX_wm_window(C); - - /* if loading new .blend while popup is open, window will be NULL */ if (win) { UI_popup_handlers_remove(&win->modalhandlers, block->handle); ui_popup_block_free(C, block->handle); diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c index 2f46c0906ae..10575fcbc54 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.c @@ -64,7 +64,7 @@ /* style + theme + layout-engine = UI */ -/* +/** * This is a complete set of layout rules, the 'state' of the Layout * Engine. Multiple styles are possible, defined via C or Python. Styles * get a name, and will typically get activated per region type, like @@ -323,10 +323,14 @@ void UI_fontstyle_draw_simple_backdrop( /* XXX: read a style configure */ uiStyle *UI_style_get(void) { +#if 0 uiStyle *style = NULL; /* offset is two struct uiStyle pointers */ - /* style = BLI_findstring(&U.uistyles, "Unifont Style", sizeof(style) * 2) */; + style = BLI_findstring(&U.uistyles, "Unifont Style", sizeof(style) * 2); return (style != NULL) ? style : U.uistyles.first; +#else + return U.uistyles.first; +#endif } /* for drawing, scaled with DPI setting */ diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index b3c31a1a644..c3b58e2d1c1 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -187,10 +187,10 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) /* preview thumbnails */ if (template.prv_rows > 0 && template.prv_cols > 0) { int w = 4 * U.widget_unit * template.prv_cols; - int h = 4 * U.widget_unit * template.prv_rows + U.widget_unit; + int h = 5 * U.widget_unit * template.prv_rows; /* fake button, it holds space for search items */ - uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL); + 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.prv_rows, template.prv_cols, ""); @@ -273,8 +273,11 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) RNA_property_pointer_set(&template->ptr, template->prop, idptr); RNA_property_update(C, &template->ptr, template->prop); - if (id && CTX_wm_window(C)->eventstate->shift) /* useful hidden functionality, */ + if (id && CTX_wm_window(C)->eventstate->shift) { + /* only way to force-remove data (on save) */ + id->flag &= ~LIB_FAKEUSER; id->us = 0; + } break; case UI_ID_FAKE_USER: @@ -359,49 +362,23 @@ static const char *template_id_browse_tip(StructRNA *type) return N_("Browse ID data to be linked"); } -/* Return a type-based i18n context, needed e.g. by "New" button. +/** + * \return a type-based i18n context, needed e.g. by "New" button. * In most languages, this adjective takes different form based on gender of type name... */ #ifdef WITH_INTERNATIONAL static const char *template_id_context(StructRNA *type) { if (type) { - switch (RNA_type_to_ID_code(type)) { - case ID_SCE: return BLF_I18NCONTEXT_ID_SCENE; - case ID_OB: return BLF_I18NCONTEXT_ID_OBJECT; - case ID_ME: return BLF_I18NCONTEXT_ID_MESH; - case ID_CU: return BLF_I18NCONTEXT_ID_CURVE; - case ID_MB: return BLF_I18NCONTEXT_ID_METABALL; - case ID_MA: return BLF_I18NCONTEXT_ID_MATERIAL; - case ID_TE: return BLF_I18NCONTEXT_ID_TEXTURE; - case ID_IM: return BLF_I18NCONTEXT_ID_IMAGE; - case ID_LS: return BLF_I18NCONTEXT_ID_FREESTYLELINESTYLE; - case ID_LT: return BLF_I18NCONTEXT_ID_LATTICE; - case ID_LA: return BLF_I18NCONTEXT_ID_LAMP; - case ID_CA: return BLF_I18NCONTEXT_ID_CAMERA; - case ID_WO: return BLF_I18NCONTEXT_ID_WORLD; - case ID_SCR: return BLF_I18NCONTEXT_ID_SCREEN; - case ID_TXT: return BLF_I18NCONTEXT_ID_TEXT; - case ID_SPK: return BLF_I18NCONTEXT_ID_SPEAKER; - case ID_SO: return BLF_I18NCONTEXT_ID_SOUND; - case ID_AR: return BLF_I18NCONTEXT_ID_ARMATURE; - case ID_AC: return BLF_I18NCONTEXT_ID_ACTION; - case ID_NT: return BLF_I18NCONTEXT_ID_NODETREE; - case ID_BR: return BLF_I18NCONTEXT_ID_BRUSH; - case ID_PA: return BLF_I18NCONTEXT_ID_PARTICLESETTINGS; - case ID_GD: return BLF_I18NCONTEXT_ID_GPENCIL; - case ID_MC: return BLF_I18NCONTEXT_ID_MOVIECLIP; - case ID_MSK: return BLF_I18NCONTEXT_ID_MASK; - case ID_PAL: return BLF_I18NCONTEXT_ID_PALETTE; - case ID_PC: return BLF_I18NCONTEXT_ID_PAINTCURVE; - } + return BKE_idcode_to_translation_context(RNA_type_to_ID_code(type)); } return BLF_I18NCONTEXT_DEFAULT; } #endif -static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag, - const char *newop, const char *openop, const char *unlinkop) +static void template_ID( + bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag, + const char *newop, const char *openop, const char *unlinkop) { uiBut *but; uiBlock *block; @@ -426,8 +403,8 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, TIP_(template_id_browse_tip(type))); - but->icon = id ? ui_id_icon_get(C, id, true) : RNA_struct_ui_icon(type); - UI_but_flag_enable(but, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); + 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); @@ -437,10 +414,9 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str else if (flag & UI_ID_BROWSE) { but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, TIP_(template_id_browse_tip(type))); - but->icon = RNA_struct_ui_icon(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_flag_enable(but, UI_HAS_ICON); UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); if ((idfrom && idfrom->lib) || !editable) @@ -617,8 +593,9 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str UI_block_align_end(block); } -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) +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) { TemplateID *template; PropertyRNA *prop; @@ -658,21 +635,24 @@ static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const MEM_freeN(template); } -void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, - const char *openop, const char *unlinkop) +void uiTemplateID( + uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop) { ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, 0, 0); } -void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, - const char *openop, const char *unlinkop) +void uiTemplateIDBrowse( + uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop) { ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME, 0, 0); } -void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, - const char *openop, const char *unlinkop, int rows, int cols) +void uiTemplateIDPreview( + uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop, int rows, int cols) { ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols); @@ -680,13 +660,15 @@ void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const c /************************ ID Chooser Template ***************************/ -/* This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use +/** + * This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use * * - propname: property identifier for property that ID-pointer gets stored to * - proptypename: property identifier for property used to determine the type of ID-pointer that can be used */ -void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, - const char *text) +void uiTemplateAnyID( + uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, + const char *text) { PropertyRNA *propID, *propType; uiLayout *split, *row, *sub; @@ -739,7 +721,8 @@ void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, co /* ---------- */ -/* This is creating/editing RNA-Paths +/** + * This is creating/editing RNA-Paths * * - ptr: struct which holds the path property * - propname: property identifier for property that path gets stored to @@ -820,10 +803,11 @@ static int modifier_is_simulation(ModifierData *md) } } -static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, - ModifierData *md, int index, int cageIndex, int lastCageIndex) +static uiLayout *draw_modifier( + uiLayout *layout, Scene *scene, Object *ob, + ModifierData *md, int index, int cageIndex, int lastCageIndex) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); PointerRNA ptr; uiBut *but; uiBlock *block; @@ -1065,7 +1049,8 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event) case B_CONSTRAINT_CHANGETARGET: { Main *bmain = CTX_data_main(C); - if (ob->pose) ob->pose->flag |= POSE_RECALC; /* checks & sorts pose channels */ + if (ob->pose) + BKE_pose_tag_recalc(bmain, ob->pose); /* checks & sorts pose channels */ DAG_relations_tag_update(bmain); break; } @@ -1095,7 +1080,7 @@ static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v) static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) { bPoseChannel *pchan = BKE_pose_channel_active(ob); - bConstraintTypeInfo *cti; + const bConstraintTypeInfo *cti; uiBlock *block; uiLayout *result = NULL, *col, *box, *row; PointerRNA ptr; @@ -1283,8 +1268,9 @@ static void do_preview_buttons(bContext *C, void *arg, int event) } } -void uiTemplatePreview(uiLayout *layout, bContext *C, ID *id, int show_buttons, ID *parent, MTex *slot, - const char *preview_id) +void uiTemplatePreview( + uiLayout *layout, bContext *C, ID *id, int show_buttons, ID *parent, MTex *slot, + const char *preview_id) { uiLayout *row, *col; uiBlock *block; @@ -1492,8 +1478,9 @@ static void colorband_update_cb(bContext *UNUSED(C), void *bt_v, void *coba_v) bt->rnapoin.data = coba->data + coba->cur; } -static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, const rctf *butr, - RNAUpdateCb *cb, int expand) +static void colorband_buttons_layout( + uiLayout *layout, uiBlock *block, ColorBand *coba, const rctf *butr, + RNAUpdateCb *cb, int expand) { uiLayout *row, *split, *subsplit; uiBut *bt; @@ -1558,6 +1545,7 @@ static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand row = uiLayoutRow(split, false); uiItemR(row, &ptr, "position", 0, IFACE_("Pos"), ICON_NONE); bt = block->buttons.last; + bt->a1 = 1.0f; /* gives a bit more precision for modifying position */ UI_but_func_set(bt, colorband_update_cb, bt, coba); row = uiLayoutRow(layout, false); @@ -1575,6 +1563,7 @@ static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand row = uiLayoutRow(subsplit, false); uiItemR(row, &ptr, "position", UI_ITEM_R_SLIDER, IFACE_("Pos"), ICON_NONE); bt = block->buttons.last; + bt->a1 = 1.0f; /* gives a bit more precision for modifying position */ UI_but_func_set(bt, colorband_update_cb, bt, coba); row = uiLayoutRow(split, false); @@ -1622,44 +1611,57 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname /********************* Icon viewer Template ************************/ +typedef struct IconViewMenuArgs { + PointerRNA ptr; + PropertyRNA *prop; + int show_labels; +} IconViewMenuArgs; /* ID Search browse menu, open */ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem) { - static RNAUpdateCb cb; + static IconViewMenuArgs args; uiBlock *block; uiBut *but; - int icon; + int icon, value; EnumPropertyItem *item; int a; bool free; /* arg_litem is malloced, can be freed by parent button */ - cb = *((RNAUpdateCb *)arg_litem); - - /* unused */ - // icon = RNA_property_enum_get(&cb.ptr, cb.prop); - - block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); + args = *((IconViewMenuArgs *) arg_litem); + + block = UI_block_begin(C, ar, "_popup", UI_EMBOSS_PULLDOWN); UI_block_flag_enable(block, UI_BLOCK_LOOP); - - - RNA_property_enum_items(C, &cb.ptr, cb.prop, &item, NULL, &free); - + + RNA_property_enum_items(C, &args.ptr, args.prop, &item, NULL, &free); + for (a = 0; item[a].identifier; a++) { int x, y; - - /* XXX hardcoded size to 5 x unit */ - x = (a % 8) * UI_UNIT_X * 5; - y = (a / 8) * UI_UNIT_X * 5; - + /* XXX hardcoded size to 5 units */ + const int w = UI_UNIT_X * 5; + const int h = args.show_labels ? 6 * UI_UNIT_Y : UI_UNIT_Y * 5; + + x = (a % 8) * w; + y = (a / 8) * h; + icon = item[a].icon; - but = uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, x, y, UI_UNIT_X * 5, UI_UNIT_Y * 5, &cb.ptr, cb.prop, -1, 0, icon, -1, -1, NULL); - UI_but_flag_enable(but, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); + value = item[a].value; + if (args.show_labels) { + but = uiDefIconTextButR_prop( + block, UI_BTYPE_ROW, 0, icon, item[a].name, x, y, w, h, + &args.ptr, args.prop, -1, 0, value, -1, -1, NULL); + } + else { + but = uiDefIconButR_prop( + block, UI_BTYPE_ROW, 0, icon, x, y, w, h, + &args.ptr, args.prop, -1, 0, value, -1, -1, NULL); + } + ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); } UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); - UI_block_direction_set(block, UI_DIR_UP); + UI_block_direction_set(block, UI_DIR_DOWN); if (free) { MEM_freeN(item); @@ -1668,40 +1670,39 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem) return block; } -void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname) +void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname, int show_labels) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); - RNAUpdateCb *cb; + IconViewMenuArgs *cb_args; + EnumPropertyItem *items; uiBlock *block; uiBut *but; -// rctf rect; /* UNUSED */ - int icon; - - if (!prop || RNA_property_type(prop) != PROP_ENUM) + int value, icon = ICON_NONE, tot_items; + bool free_items; + + if (!prop || RNA_property_type(prop) != PROP_ENUM) { + RNA_warning("property of type Enum not found: %s.%s", RNA_struct_identifier(ptr->type), propname); return; - - icon = RNA_property_enum_get(ptr, prop); - - cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); - cb->ptr = *ptr; - cb->prop = prop; - -// rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X; -// rect.ymin = 0; rect.ymax = 10.0f * UI_UNIT_X; - + } + block = uiLayoutAbsoluteBlock(layout); - but = uiDefBlockButN(block, ui_icon_view_menu_cb, MEM_dupallocN(cb), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); + RNA_property_enum_items(block->evil_C, ptr, prop, &items, &tot_items, &free_items); + value = RNA_property_enum_get(ptr, prop); + RNA_enum_icon_from_value(items, value, &icon); - -// but = uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, 0, 0, BLI_rctf_size_x(&rect), BLI_rctf_size_y(&rect), ptr, prop, -1, 0, icon, -1, -1, NULL); - - but->icon = icon; - UI_but_flag_enable(but, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); - - UI_but_funcN_set(but, rna_update_cb, MEM_dupallocN(cb), NULL); - - MEM_freeN(cb); + cb_args = MEM_callocN(sizeof(IconViewMenuArgs), __func__); + cb_args->ptr = *ptr; + cb_args->prop = prop; + cb_args->show_labels = show_labels; + + but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb_args, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); + + ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); + + if (free_items) { + MEM_freeN(items); + } } /********************* Histogram Template ************************/ @@ -2071,8 +2072,9 @@ static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v) } /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */ -static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, - int brush, int neg_slope, RNAUpdateCb *cb) +static void curvemap_buttons_layout( + uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, + int brush, int neg_slope, RNAUpdateCb *cb) { CurveMapping *cumap = ptr->data; CurveMap *cm = &cumap->cm[cumap->cur]; @@ -2233,8 +2235,9 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe UI_block_funcN_set(block, NULL, NULL, NULL); } -void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propname, int type, - int levels, int brush, int neg_slope) +void uiTemplateCurveMapping( + uiLayout *layout, PointerRNA *ptr, const char *propname, int type, + int levels, int brush, int neg_slope) { RNAUpdateCb *cb; PropertyRNA *prop = RNA_struct_find_property(ptr, propname); @@ -2277,8 +2280,9 @@ void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propn #define WHEEL_SIZE (5 * U.widget_unit) /* This template now follows User Preference for type - name is not correct anymore... */ -void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, - int lock, int lock_luminosity, int cubic) +void uiTemplateColorPicker( + uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, + int lock, int lock_luminosity, int cubic) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); uiBlock *block = uiLayoutGetBlock(layout); @@ -2398,9 +2402,6 @@ void uiTemplatePalette(uiLayout *layout, PointerRNA *ptr, const char *propname, palette = cptr.data; - /* first delete any pending colors */ - BKE_palette_cleanup(palette); - color = palette->colors.first; col = uiLayoutColumn(layout, true); @@ -2452,12 +2453,13 @@ static void handle_layer_buttons(bContext *C, void *arg1, void *arg2) /* see view3d_header.c */ } -/* TODO: - * - for now, grouping of layers is determined by dividing up the length of - * the array of layer bitflags */ - -void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname, - PointerRNA *used_ptr, const char *used_propname, int active_layer) +/** + * \todo for now, grouping of layers is determined by dividing up the length of + * the array of layer bitflags + */ +void uiTemplateLayers( + uiLayout *layout, PointerRNA *ptr, const char *propname, + PointerRNA *used_ptr, const char *used_propname, int active_layer) { uiLayout *uRow, *uCol; PropertyRNA *prop, *used_prop = NULL; @@ -2523,8 +2525,9 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname, } } -void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propname, - PointerRNA *used_ptr, const char *used_propname, int active_state) +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; @@ -2594,10 +2597,11 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam /************************* List Template **************************/ -static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout, - struct PointerRNA *UNUSED(dataptr), struct PointerRNA *itemptr, int icon, - struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname), - int UNUSED(index), int UNUSED(flt_flag)) +static void uilist_draw_item_default( + struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout, + struct PointerRNA *UNUSED(dataptr), struct PointerRNA *itemptr, int icon, + struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname), + int UNUSED(index), int UNUSED(flt_flag)) { PropertyRNA *nameprop = RNA_struct_name_property(itemptr->type); @@ -2764,8 +2768,9 @@ typedef struct { int end_idx; /* Index of last item to display + 1. */ } uiListLayoutdata; -static void uilist_prepare(uiList *ui_list, int len, int activei, int rows, int maxrows, int columns, - uiListLayoutdata *layoutdata) +static void uilist_prepare( + uiList *ui_list, int len, int activei, int rows, int maxrows, int columns, + uiListLayoutdata *layoutdata) { uiListDyn *dyn_data = ui_list->dyn_data; int activei_row, max_scroll; @@ -2851,9 +2856,10 @@ static char *uilist_item_tooltip_func(bContext *UNUSED(C), void *argN, const cha return BLI_sprintfN("%s - %s", tip, dyn_tooltip); } -void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id, - PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname, - const char *item_dyntip_propname, int rows, int maxrows, int layout_type, int columns) +void uiTemplateList( + uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id, + PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname, + const char *item_dyntip_propname, int rows, int maxrows, int layout_type, int columns) { uiListType *ui_list_type; uiList *ui_list = NULL; @@ -3199,7 +3205,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co /* add scrollbar */ if (len > layoutdata.visual_items) { - col = uiLayoutColumn(row, false); + /* col = */ uiLayoutColumn(row, false); uiDefButI(block, UI_BTYPE_SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height, &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height, dyn_data->visual_height, 0, ""); @@ -3277,17 +3283,18 @@ static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { wmOperatorType *ot = BLI_ghashIterator_getValue(&iter); + const char *ot_ui_name = CTX_IFACE_(ot->translation_context, ot->name); if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) continue; - if (BLI_strcasestr(ot->name, str)) { + if (BLI_strcasestr(ot_ui_name, str)) { if (WM_operator_poll((bContext *)C, ot)) { char name[256]; - int len = strlen(ot->name); + int len = strlen(ot_ui_name); /* display name for menu, can hold hotkey */ - BLI_strncpy(name, ot->name, sizeof(name)); + BLI_strncpy(name, ot_ui_name, sizeof(name)); /* check for hotkey */ if (len < sizeof(name) - 6) { diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 28bd637ae59..0823238fcb1 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -52,6 +52,9 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "WM_api.h" +#include "WM_types.h" + #include "interface_intern.h" @@ -154,9 +157,10 @@ 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(uiLayout *layout, PointerRNA *ptr, - bool (*check_prop)(PointerRNA *, PropertyRNA *), - const char label_align) +int uiDefAutoButsRNA( + uiLayout *layout, PointerRNA *ptr, + bool (*check_prop)(PointerRNA *, PropertyRNA *), + const char label_align) { uiLayout *split, *col; int flag; @@ -309,6 +313,34 @@ int UI_calc_float_precision(int prec, double value) return prec; } +bool UI_but_online_manual_id(const uiBut *but, char *r_str, size_t maxlength) +{ + if (but->rnapoin.id.data && but->rnapoin.data && but->rnaprop) { + BLI_snprintf(r_str, maxlength, "%s.%s", RNA_struct_identifier(but->rnapoin.type), + RNA_property_identifier(but->rnaprop)); + return true; + } + else if (but->optype) { + WM_operator_py_idname(r_str, but->optype->idname); + return true; + } + + *r_str = '\0'; + return false; +} + +bool UI_but_online_manual_id_from_active(const struct bContext *C, char *r_str, size_t maxlength) +{ + uiBut *but = UI_context_active_but_get(C); + + if (but) { + return UI_but_online_manual_id(but, r_str, maxlength); + } + + *r_str = '\0'; + return false; +} + /* -------------------------------------------------------------------- */ /* Modal Button Store API */ diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 91186a14b49..253f4616843 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -27,7 +27,6 @@ * \ingroup edinterface */ - #include <limits.h> #include <stdlib.h> #include <string.h> @@ -56,7 +55,6 @@ #include "UI_interface.h" #include "UI_interface_icons.h" - #include "interface_intern.h" #ifdef WITH_INPUT_IME @@ -67,12 +65,12 @@ #define ICON_SIZE_FROM_BUTRECT(rect) (0.8f * BLI_rcti_size_y(rect)) /* ************** widget base functions ************** */ -/* +/** * - in: roundbox codes for corner types and radius - * - return: array of [size][2][x,y] points, the edges of the roundbox, + UV coords + * - return: array of `[size][2][x, y]` points, the edges of the roundbox, + UV coords * * - draw black box with alpha 0 on exact button boundbox - * - for ever AA step: + * - for every AA step: * - draw the inner part for a round filled box, with color blend codes or texture coords * - draw outline in outline color * - draw outer part, bottom half, extruded 1 pixel to bottom, for emboss shadow @@ -102,14 +100,14 @@ typedef struct uiWidgetBase { float inner_v[WIDGET_SIZE_MAX][2]; float inner_uv[WIDGET_SIZE_MAX][2]; - bool inner, outline, emboss, shadedir; + bool draw_inner, draw_outline, draw_emboss, draw_shadedir; uiWidgetTrias tria1; uiWidgetTrias tria2; } uiWidgetBase; -/* uiWidgetType: for time being only for visual appearance, +/** uiWidgetType: for time being only for visual appearance, * later, a handling callback can be added too */ typedef struct uiWidgetType { @@ -239,10 +237,10 @@ static void widget_init(uiWidgetBase *wtb) wtb->tria1.tot = 0; wtb->tria2.tot = 0; - wtb->inner = 1; - wtb->outline = 1; - wtb->emboss = 1; - wtb->shadedir = 1; + wtb->draw_inner = true; + wtb->draw_outline = true; + wtb->draw_emboss = true; + wtb->draw_shadedir = true; } /* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */ @@ -549,12 +547,12 @@ static void widget_menu_trias(uiWidgetTrias *tria, const rcti *rect) { float centx, centy, size; int a; - + /* 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 * (float)BLI_rcti_size_y(rect); - + size = 0.4f * BLI_rcti_size_y(rect); + for (a = 0; a < 6; a++) { tria->vec[a][0] = size * menu_tria_vert[a][0] + centx; tria->vec[a][1] = size * menu_tria_vert[a][1] + centy; @@ -587,7 +585,6 @@ static void widget_check_trias(uiWidgetTrias *tria, const rcti *rect) /* prepares shade colors */ static void shadecolors4(char coltop[4], char coldown[4], const char *color, short shadetop, short shadedown) { - coltop[0] = CLAMPIS(color[0] + shadetop, 0, 255); coltop[1] = CLAMPIS(color[1] + shadetop, 0, 255); coltop[2] = CLAMPIS(color[2] + shadetop, 0, 255); @@ -604,10 +601,10 @@ static void round_box_shade_col4_r(unsigned char r_col[4], const char col1[4], c const int faci = FTOCHAR(fac); const int facm = 255 - faci; - r_col[0] = (faci * col1[0] + facm * col2[0]) >> 8; - r_col[1] = (faci * col1[1] + facm * col2[1]) >> 8; - r_col[2] = (faci * col1[2] + facm * col2[2]) >> 8; - r_col[3] = (faci * col1[3] + facm * col2[3]) >> 8; + r_col[0] = (faci * col1[0] + facm * col2[0]) / 256; + r_col[1] = (faci * col1[1] + facm * col2[1]) / 256; + r_col[2] = (faci * col1[2] + facm * col2[2]) / 256; + r_col[3] = (faci * col1[3] + facm * col2[3]) / 256; } static void widget_verts_to_triangle_strip(uiWidgetBase *wtb, const int totvert, float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]) @@ -650,7 +647,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) glEnable(GL_BLEND); /* backdrop non AA */ - if (wtb->inner) { + if (wtb->draw_inner) { if (wcol->shaded == 0) { if (wcol->alpha_check) { float inner_v_half[WIDGET_SIZE_MAX][2]; @@ -716,7 +713,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) glShadeModel(GL_SMOOTH); for (a = 0; a < wtb->totvert; a++, col_pt += 4) { - round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->shadedir]); + round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->draw_shadedir ? 1 : 0]); } glEnableClientState(GL_VERTEX_ARRAY); @@ -732,7 +729,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) } /* for each AA step */ - if (wtb->outline) { + if (wtb->draw_outline) { 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 */ @@ -743,7 +740,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip); - if (wtb->emboss) { + if (wtb->draw_emboss) { widget_verts_to_triangle_strip_open(wtb, wtb->halfwayvert, triangle_strip_emboss); } @@ -761,7 +758,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2); /* emboss bottom shadow */ - if (wtb->emboss) { + if (wtb->draw_emboss) { UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss); if (emboss[3]) { @@ -783,6 +780,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) wcol->item[1], wcol->item[2], (unsigned char)((float)wcol->item[3] / WIDGET_AA_JITTER)}; + /* for each AA step */ for (j = 0; j < WIDGET_AA_JITTER; j++) { glTranslatef(jit[j][0], jit[j][1], 0.0f); @@ -801,7 +799,6 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) } glDisable(GL_BLEND); - } /* *********************** text/icon ************************************** */ @@ -810,7 +807,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) #define PREVIEW_PAD 4 -static void widget_draw_preview(BIFIconID icon, float UNUSED(alpha), const rcti *rect) +static void widget_draw_preview(BIFIconID icon, float alpha, const rcti *rect) { int w, h, size; @@ -826,7 +823,7 @@ static void widget_draw_preview(BIFIconID icon, float UNUSED(alpha), const rcti int x = rect->xmin + w / 2 - size / 2; int y = rect->ymin + h / 2 - size / 2; - UI_icon_draw_preview_aspect_size(x, y, icon, 1.0f, size); + UI_icon_draw_preview_aspect_size(x, y, icon, 1.0f, alpha, size); } } @@ -838,8 +835,9 @@ 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(const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, - const bool show_menu_icon) +static void widget_draw_icon( + const uiBut *but, BIFIconID icon, float alpha, const rcti *rect, + const bool show_menu_icon) { float xs = 0.0f, ys = 0.0f; float aspect, height; @@ -875,7 +873,7 @@ static void widget_draw_icon(const uiBut *but, BIFIconID icon, float alpha, cons if (but->drawflag & UI_BUT_ICON_LEFT) { if (but->block->flag & UI_BLOCK_LOOP) { - if (ELEM(but->type, UI_BTYPE_SEARCH_MENU, UI_BTYPE_SEARCH_MENU_UNLINK)) + if (but->type == UI_BTYPE_SEARCH_MENU) xs = rect->xmin + 4.0f * ofs; else xs = rect->xmin + ofs; @@ -931,12 +929,14 @@ static void ui_text_clip_give_next_off(uiBut *but, const char *str) but->ofs += bytes; } -/* Helper. +/** + * Helper. * This func assumes things like kerning handling have already been handled! * Return the length of modified (right-clipped + ellipsis) string. */ -static void ui_text_clip_right_ex(uiFontStyle *fstyle, char *str, const size_t max_len, const float okwidth, - const char *sep, const int sep_len, const float sep_strwidth, size_t *r_final_len) +static void ui_text_clip_right_ex( + uiFontStyle *fstyle, char *str, const size_t max_len, const float okwidth, + const char *sep, const int sep_len, const float sep_strwidth, size_t *r_final_len) { float tmp; int l_end; @@ -968,11 +968,16 @@ static void ui_text_clip_right_ex(uiFontStyle *fstyle, char *str, const size_t m * If rpart_sep is not Null, the part of str starting to first occurrence of rpart_sep is preserved at all cost (useful * for strings with shortcuts, like 'AVeryLongFooBarLabelForMenuEntry|Ctrl O' -> 'AVeryLong...MenuEntry|Ctrl O'). */ -static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, float okwidth, const float minwidth, - const size_t max_len, const char *rpart_sep) +float UI_text_clip_middle_ex( + uiFontStyle *fstyle, char *str, float okwidth, const float minwidth, + const size_t max_len, const char rpart_sep) { float strwidth; + /* Add some epsilon to OK width, avoids 'ellipsing' text that nearly fits! + * Better to have a small piece of the last char cut out, than two remaining chars replaced by an allipsis... */ + okwidth += 1.0f + UI_DPI_FAC; + BLI_assert(str[0]); /* need to set this first */ @@ -998,7 +1003,7 @@ static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, float okwidt size_t final_lpart_len; if (rpart_sep) { - rpart = strstr(str, rpart_sep); + rpart = strrchr(str, rpart_sep); if (rpart) { rpart_len = strlen(rpart); @@ -1069,7 +1074,7 @@ static float ui_text_clip_middle_ex(uiFontStyle *fstyle, char *str, float okwidt } /** - * Wrapper around ui_text_clip_middle_ex. + * Wrapper around UI_text_clip_middle_ex. */ static void ui_text_clip_middle(uiFontStyle *fstyle, uiBut *but, const rcti *rect) { @@ -1080,14 +1085,14 @@ static void ui_text_clip_middle(uiFontStyle *fstyle, uiBut *but, const rcti *rec const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f; but->ofs = 0; - but->strwidth = ui_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, NULL); + but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, '\0'); } /** * Like ui_text_clip_middle(), but protect/preserve at all cost the right part of the string after sep. * Useful for strings with shortcuts (like 'AVeryLongFooBarLabelForMenuEntry|Ctrl O' -> 'AVeryLong...MenuEntry|Ctrl O'). */ -static void ui_text_clip_middle_protect_right(uiFontStyle *fstyle, uiBut *but, const rcti *rect, const char *rsep) +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); @@ -1096,7 +1101,7 @@ static void ui_text_clip_middle_protect_right(uiFontStyle *fstyle, uiBut *but, c const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f; but->ofs = 0; - but->strwidth = ui_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, rsep); + but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, rsep); } /** @@ -1217,7 +1222,6 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs); if (but->strwidth < 10) break; } - } @@ -1320,7 +1324,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b #ifdef WITH_INPUT_IME /* FIXME, IME is modifying 'const char *drawstr! */ - ime_data = ui_but_get_ime_data(but); + ime_data = ui_but_ime_data_get(but); if (ime_data && ime_data->composite_len) { /* insert composite string into cursor pos */ @@ -1384,7 +1388,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b t = 0; } - glColor3f(0.20, 0.6, 0.9); + glColor3f(0.2, 0.6, 0.9); tx = rect->xmin + t + 2; ty = rect->ymin + 2; @@ -1505,6 +1509,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB const bool show_menu_icon = ui_but_draw_menu_icon(but); float alpha = (float)wcol->text[3] / 255.0f; char password_str[UI_MAX_DRAW_STR]; + uiButExtraIconType extra_icon_type; ui_but_text_password_hide(password_str, but, false); @@ -1518,7 +1523,34 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB /* If there's an icon too (made with uiDefIconTextBut) then draw the icon * and offset the text label to accommodate it */ - if (but->flag & UI_HAS_ICON || show_menu_icon) { + /* Big previews with optional text label below */ + if (but->flag & UI_BUT_ICON_PREVIEW && ui_block_is_menu(but->block)) { + const BIFIconID icon = (but->flag & UI_HAS_ICON) ? but->icon + but->iconadd : ICON_NONE; + int icon_size = BLI_rcti_size_y(rect); + int text_size = 0; + + /* This is a bit britle, but avoids adding an 'UI_BUT_HAS_LABEL' flag to but... */ + if (icon_size > BLI_rcti_size_x(rect)) { + /* button is not square, it has extra height for label */ + text_size = UI_UNIT_Y; + icon_size -= text_size; + } + + /* draw icon in rect above the space reserved for the label */ + rect->ymin += text_size; + glEnable(GL_BLEND); + widget_draw_preview(icon, alpha, rect); + glDisable(GL_BLEND); + + /* offset rect to draw label in */ + rect->ymin -= text_size; + rect->ymax -= icon_size; + + /* vertically centering text */ + rect->ymin += UI_UNIT_Y / 2; + } + /* Icons on the left with optional text label on the right */ + else if (but->flag & UI_HAS_ICON || show_menu_icon) { const BIFIconID icon = (but->flag & UI_HAS_ICON) ? but->icon + but->iconadd : ICON_NONE; const float icon_size = ICON_SIZE_FROM_BUTRECT(rect); @@ -1544,11 +1576,23 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB } /* unlink icon for this button type */ - if ((but->type == UI_BTYPE_SEARCH_MENU_UNLINK) && ui_but_is_search_unlink_visible(but)) { + if ((but->type == UI_BTYPE_SEARCH_MENU) && + ((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE)) + { rcti temp = *rect; temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f); - widget_draw_icon(but, ICON_X, alpha, &temp, false); + + if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) { + widget_draw_icon(but, ICON_X, alpha, &temp, false); + } + else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) { + widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, false); + } + else { + BLI_assert(0); + } + rect->xmax -= ICON_SIZE_FROM_BUTRECT(rect); } @@ -1564,9 +1608,9 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB else if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) { ui_text_clip_right_label(fstyle, but, rect); } - else if ((but->block->flag & UI_BLOCK_LOOP) && (but->type == UI_BTYPE_BUT)) { + else if (but->flag & UI_BUT_HAS_SEP_CHAR) { /* Clip middle, but protect in all case right part containing the shortcut, if any. */ - ui_text_clip_middle_protect_right(fstyle, but, rect, "|"); + ui_text_clip_middle_protect_right(fstyle, but, rect, UI_SEP_CHAR); } else { ui_text_clip_middle(fstyle, but, rect); @@ -1583,17 +1627,6 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB /* *********************** widget types ************************************* */ - -/* uiWidgetStateColors - * char inner_anim[4]; - * char inner_anim_sel[4]; - * char inner_key[4]; - * char inner_key_sel[4]; - * char inner_driven[4]; - * char inner_driven_sel[4]; - * float blend; - */ - static struct uiWidgetStateColors wcol_state_colors = { {115, 190, 76, 255}, {90, 166, 51, 255}, @@ -1604,18 +1637,6 @@ static struct uiWidgetStateColors wcol_state_colors = { 0.5f, 0.0f }; -/* uiWidgetColors - * char outline[3]; - * char inner[4]; - * char inner_sel[4]; - * char item[3]; - * char text[3]; - * char text_sel[3]; - * - * short shaded; - * float shadetop, shadedown; - */ - static struct uiWidgetColors wcol_num = { {25, 25, 25, 255}, {180, 180, 180, 255}, @@ -1746,7 +1767,7 @@ static struct uiWidgetColors wcol_tooltip = { {45, 45, 45, 230}, {100, 100, 100, 255}, - {160, 160, 160, 255}, + {255, 255, 255, 255}, {255, 255, 255, 255}, 0, @@ -2181,7 +2202,7 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir widget_softshadow(rect, roundboxalign, 0.25f * U.widget_unit); round_box_edges(&wtb, roundboxalign, rect, 0.25f * U.widget_unit); - wtb.emboss = 0; + wtb.draw_emboss = false; widgetbase_draw(&wtb, wcol); glDisable(GL_BLEND); @@ -2190,7 +2211,6 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir static void ui_hsv_cursor(float x, float y) { - glPushMatrix(); glTranslatef(x, y, 0.0f); @@ -2205,7 +2225,6 @@ static void ui_hsv_cursor(float x, float y) glDisable(GL_LINE_SMOOTH); glPopMatrix(); - } void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect, @@ -2280,12 +2299,12 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti * * Useful for color correction tools where you're only interested in hue. */ if (but->flag & UI_BUT_COLOR_LOCK) { if (U.color_picker_type == USER_CP_CIRCLE_HSV) - hsv[2] = 1.f; + hsv[2] = 1.0f; else hsv[2] = 0.5f; } - ui_color_picker_to_rgb(0.f, 0.f, hsv[2], colcent, colcent + 1, colcent + 2); + ui_color_picker_to_rgb(0.0f, 0.0f, hsv[2], colcent, colcent + 1, colcent + 2); glShadeModel(GL_SMOOTH); @@ -2331,7 +2350,7 @@ 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.0 / 48.0); + const float color_step = 1.0f / 48.0f; int a; float h = hsv[0], s = hsv[1], v = hsv[2]; float dx, dy, sx1, sx2, sy; @@ -2344,9 +2363,9 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons switch (type) { case UI_GRAD_SV: hsv_to_rgb(h, 0.0, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); - hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]); - hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]); - hsv_to_rgb(h, 1.0, 0.0, &col1[3][0], &col1[3][1], &col1[3][2]); + hsv_to_rgb(h, 0.0, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(h, 0.0, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(h, 0.0, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]); break; case UI_GRAD_HV: hsv_to_rgb(0.0, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); @@ -2361,26 +2380,26 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons hsv_to_rgb(0.0, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]); break; case UI_GRAD_H: - hsv_to_rgb(0.0, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]); + hsv_to_rgb(0.0, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]); copy_v3_v3(col1[1], col1[0]); copy_v3_v3(col1[2], col1[0]); copy_v3_v3(col1[3], col1[0]); break; case UI_GRAD_S: - hsv_to_rgb(1.0, 0.0, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(1.0, 0.0, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]); copy_v3_v3(col1[0], col1[1]); copy_v3_v3(col1[2], col1[1]); copy_v3_v3(col1[3], col1[1]); break; case UI_GRAD_V: - hsv_to_rgb(1.0, 1.0, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(1.0, 1.0, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]); copy_v3_v3(col1[0], col1[2]); copy_v3_v3(col1[1], col1[2]); copy_v3_v3(col1[3], col1[2]); break; default: assert(!"invalid 'type' argument"); - hsv_to_rgb(1.0, 1.0, 1.0, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(1.0, 1.0, 1.0, &col1[2][0], &col1[2][1], &col1[2][2]); copy_v3_v3(col1[0], col1[2]); copy_v3_v3(col1[1], col1[2]); copy_v3_v3(col1[3], col1[2]); @@ -2401,10 +2420,10 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons /* new color */ switch (type) { case UI_GRAD_SV: - hsv_to_rgb(h, 0.0, dx, &col1[0][0], &col1[0][1], &col1[0][2]); - hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]); - hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]); - hsv_to_rgb(h, 1.0, dx, &col1[3][0], &col1[3][1], &col1[3][2]); + hsv_to_rgb(h, dx, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); + hsv_to_rgb(h, dx, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(h, dx, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(h, dx, 1.0, &col1[3][0], &col1[3][1], &col1[3][2]); break; case UI_GRAD_HV: hsv_to_rgb(dx_next, s, 0.0, &col1[0][0], &col1[0][1], &col1[0][2]); @@ -2419,23 +2438,21 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons hsv_to_rgb(dx_next, 1.0, v, &col1[3][0], &col1[3][1], &col1[3][2]); break; case UI_GRAD_H: - { /* annoying but without this the color shifts - could be solved some other way * - campbell */ - hsv_to_rgb(dx_next, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]); + hsv_to_rgb(dx_next, 1.0, 1.0, &col1[0][0], &col1[0][1], &col1[0][2]); copy_v3_v3(col1[1], col1[0]); copy_v3_v3(col1[2], col1[0]); copy_v3_v3(col1[3], col1[0]); break; - } case UI_GRAD_S: - hsv_to_rgb(h, dx, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]); + hsv_to_rgb(h, dx, 1.0, &col1[1][0], &col1[1][1], &col1[1][2]); copy_v3_v3(col1[0], col1[1]); copy_v3_v3(col1[2], col1[1]); copy_v3_v3(col1[3], col1[1]); break; case UI_GRAD_V: - hsv_to_rgb(h, 1.0, dx, &col1[2][0], &col1[2][1], &col1[2][2]); + hsv_to_rgb(h, 1.0, dx, &col1[2][0], &col1[2][1], &col1[2][2]); copy_v3_v3(col1[0], col1[2]); copy_v3_v3(col1[1], col1[2]); copy_v3_v3(col1[3], col1[2]); @@ -2464,9 +2481,8 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons } glEnd(); } - + glShadeModel(GL_FLAT); - } bool ui_but_is_colorpicker_display_space(uiBut *but) @@ -2487,7 +2503,7 @@ void ui_hsvcube_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float *x switch ((int)but->a1) { case UI_GRAD_SV: - x = hsv[2]; y = hsv[1]; break; + x = hsv[1]; y = hsv[2]; break; case UI_GRAD_HV: x = hsv[0]; y = hsv[2]; break; case UI_GRAD_HS: @@ -2509,11 +2525,10 @@ void ui_hsvcube_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float *x y = (hsv[2] - but->softmin) / (but->softmax - but->softmin); break; } - + /* cursor */ *xp = rect->xmin + x * BLI_rcti_size_x(rect); *yp = rect->ymin + y * BLI_rcti_size_y(rect); - } static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect) @@ -2594,9 +2609,8 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect) x = rect->xmin + 0.5f * BLI_rcti_size_x(rect); y = rect->ymin + v * BLI_rcti_size_y(rect); CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f); - + ui_hsv_cursor(x, y); - } @@ -2681,7 +2695,8 @@ bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol) 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])); - return 1; + /* TODO: why return anything if always true? */ + return true; } #define LINK_RESOL 24 @@ -2690,9 +2705,10 @@ 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; // UNUSED - + const float dist = 1.0f / (float)LINK_RESOL; +#endif glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); @@ -2703,7 +2719,6 @@ void ui_draw_link_bezier(const rcti *rect) glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - } } @@ -2725,7 +2740,7 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s else rad = 0.5f * BLI_rcti_size_x(rect); - wtb.shadedir = (horizontal) ? 1 : 0; + wtb.draw_shadedir = (horizontal) ? true : false; /* draw back part, colors swapped and shading inverted */ if (horizontal) @@ -2754,11 +2769,11 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s } /* draw */ - wtb.emboss = 0; /* only emboss once */ + wtb.draw_emboss = false; /* only emboss once */ /* exception for progress bar */ if (state & UI_SCROLL_NO_OUTLINE) { - SWAP(bool, outline, wtb.outline); + SWAP(bool, outline, wtb.draw_outline); } round_box_edges(&wtb, UI_CNR_ALL, slider, rad); @@ -2781,7 +2796,7 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s widgetbase_draw(&wtb, wcol); if (state & UI_SCROLL_NO_OUTLINE) { - SWAP(bool, outline, wtb.outline); + SWAP(bool, outline, wtb.draw_outline); } } } @@ -2908,7 +2923,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s toffs = offs * 0.75f; round_box_edges(&wtb, roundboxalign, rect, offs); - wtb.outline = 0; + wtb.draw_outline = false; widgetbase_draw(&wtb, wcol); /* draw left/right parts only when not in text editing */ @@ -2933,7 +2948,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s /* 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.outline = 0; + wtb1.draw_outline = false; widgetbase_draw(&wtb1, wcol); /* right part of slider, interpolate roundness */ @@ -2958,8 +2973,8 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s } /* outline */ - wtb.outline = 1; - wtb.inner = 0; + 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) */ @@ -2967,7 +2982,6 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s rect->xmax -= toffs; rect->xmin += toffs; } - } /* I think 3 is sufficient border to indicate keyed status */ @@ -3027,7 +3041,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat float width = rect->xmax - rect->xmin; float height = rect->ymax - rect->ymin; /* find color luminance and change it slightly */ - float bw = rgb_to_bw(col); + float bw = rgb_to_grayscale(col); bw += (bw < 0.5f) ? 0.5f : -0.5f; @@ -3052,7 +3066,7 @@ static void widget_icon_has_anim(uiBut *but, uiWidgetColors *wcol, rcti *rect, i float rad; widget_init(&wtb); - wtb.outline = 0; + wtb.draw_outline = false; /* rounded */ rad = 0.5f * BLI_rcti_size_y(rect); @@ -3082,7 +3096,6 @@ static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roun round_box_edges(&wtb, roundboxalign, rect, rad); widgetbase_draw(&wtb, wcol); - } @@ -3168,7 +3181,7 @@ static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(sta widget_init(&wtb); /* not rounded, no outline */ - wtb.outline = 0; + wtb.draw_outline = false; round_box_edges(&wtb, 0, rect, 0.0f); widgetbase_draw(&wtb, wcol); @@ -3182,7 +3195,7 @@ static void widget_menu_radial_itembut(uiBut *but, uiWidgetColors *wcol, rcti *r widget_init(&wtb); - wtb.emboss = 0; + wtb.draw_emboss = false; rad = 0.5f * BLI_rcti_size_y(rect); round_box_edges(&wtb, UI_CNR_ALL, rect, rad); @@ -3205,7 +3218,7 @@ static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(sta widget_init(&wtb); /* rounded, but no outline */ - wtb.outline = 0; + wtb.draw_outline = false; rad = 0.2f * U.widget_unit; round_box_edges(&wtb, UI_CNR_ALL, rect, rad); @@ -3278,7 +3291,6 @@ static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), round_box_edges(&wtb, roundboxalign, rect, rad); widgetbase_draw(&wtb, wcol); - } static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign) @@ -3319,7 +3331,6 @@ static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int round_box_edges(&wtb, roundboxalign, rect, rad); widgetbase_draw(&wtb, wcol); - } static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign) @@ -3360,10 +3371,9 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType * /* outline */ round_box_edges(&wtb, UI_CNR_ALL, rect, rad); - wtb.outline = 1; - wtb.inner = 0; + wtb.draw_outline = true; + wtb.draw_inner = false; widgetbase_draw(&wtb, &wt->wcol); - } static uiWidgetType *widget_type(uiWidgetTypeEnum type) @@ -3653,8 +3663,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct case UI_BTYPE_TEXT: wt = widget_type(UI_WTYPE_NAME); break; - - case UI_BTYPE_SEARCH_MENU_UNLINK: + case UI_BTYPE_SEARCH_MENU: wt = widget_type(UI_WTYPE_NAME); if (but->block->flag & UI_BLOCK_LOOP) @@ -3931,7 +3940,6 @@ static void draw_disk_shaded( glVertex2f(c * radius_ext, s * radius_ext); } glEnd(); - } void ui_draw_pie_center(uiBlock *block) @@ -4020,7 +4028,6 @@ void ui_draw_search_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect) wt->draw(&wt->wcol, rect, block->flag, UI_CNR_ALL); else wt->draw(&wt->wcol, rect, 0, UI_CNR_ALL); - } @@ -4070,7 +4077,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic const float minwidth = (float)(UI_DPI_ICON_SIZE); BLI_strncpy(drawstr, name, sizeof(drawstr)); - ui_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, NULL); + UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0'); glColor4ubv((unsigned char *)wt->wcol.text); UI_fontstyle_draw(fstyle, rect, drawstr); @@ -4105,39 +4112,31 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state) { - rcti trect = *rect, bg_rect; + rcti trect = *rect; + const float text_size = UI_UNIT_Y; float font_dims[2] = {0.0f, 0.0f}; uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM); + /* drawing button background */ wt->state(wt, state); wt->draw(&wt->wcol, rect, 0, 0); + /* draw icon in rect above the space reserved for the label */ + rect->ymin += text_size; glEnable(GL_BLEND); widget_draw_preview(iconid, 1.0f, rect); + glDisable(GL_BLEND); BLF_width_and_height(fstyle->uifont_id, name, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]); /* text rect */ trect.xmin += 0; - trect.xmax = trect.xmin + font_dims[0] + 10; - trect.ymin += 10; + trect.xmax = trect.xmin + font_dims[0] + U.widget_unit / 2; + trect.ymin += U.widget_unit / 2; trect.ymax = trect.ymin + font_dims[1]; if (trect.xmax > rect->xmax - PREVIEW_PAD) trect.xmax = rect->xmax - PREVIEW_PAD; - bg_rect = trect; - bg_rect.xmin = rect->xmin + PREVIEW_PAD; - bg_rect.ymin = rect->ymin + PREVIEW_PAD; - bg_rect.xmax = rect->xmax - PREVIEW_PAD; - bg_rect.ymax += PREVIEW_PAD / 2; - - if (bg_rect.xmax > rect->xmax - PREVIEW_PAD) - bg_rect.xmax = rect->xmax - PREVIEW_PAD; - - glColor4ubv((unsigned char *)wt->wcol_theme->inner_sel); - glRecti(bg_rect.xmin, bg_rect.ymin, bg_rect.xmax, bg_rect.ymax); - glDisable(GL_BLEND); - { char drawstr[UI_MAX_DRAW_STR]; const float okwidth = (float)BLI_rcti_size_x(&trect); @@ -4145,7 +4144,7 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int const float minwidth = (float)(UI_DPI_ICON_SIZE); BLI_strncpy(drawstr, name, sizeof(drawstr)); - ui_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, NULL); + UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0'); glColor4ubv((unsigned char *)wt->wcol.text); UI_fontstyle_draw(fstyle, &trect, drawstr); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index a9cc53852c0..68016ae3dd8 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -569,6 +569,13 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo cp = ts->paint_curve_pivot; break; + case TH_METADATA_BG: + cp = ts->metadatabg; + break; + case TH_METADATA_TEXT: + cp = ts->metadatatext; + break; + case TH_UV_OTHERS: cp = ts->uv_others; break; @@ -817,8 +824,9 @@ static void ui_theme_space_init_handles_color(ThemeSpace *theme_space) 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 +/** + * initialize default theme + * \note: when you add new colors, created & saved themes need initialized * use function below, init_userdef_do_versions() */ void ui_theme_init_default(void) @@ -1098,7 +1106,7 @@ void ui_theme_init_default(void) 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); /* Grey (mix between fg/bg) */ + rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Gray (mix between fg/bg) */ /* space oops */ btheme->toops = btheme->tv3d; @@ -1504,8 +1512,9 @@ void UI_GetColorPtrShade3ubv(const unsigned char cp[3], unsigned char col[3], in } /* get a 3 byte color, blended and shaded between two other char color pointers */ -void UI_GetColorPtrBlendShade3ubv(const unsigned char cp1[3], const unsigned char cp2[3], unsigned char col[3], - float fac, int offset) +void UI_GetColorPtrBlendShade3ubv( + const unsigned char cp1[3], const unsigned char cp2[3], unsigned char col[3], + float fac, int offset) { int r, g, b; @@ -1603,8 +1612,8 @@ void init_userdef_do_versions(void) U.tw_size = 25; /* percentage of window size */ U.tw_handlesize = 16; /* percentage of widget radius */ } - if (U.pad_rot_angle == 0) - U.pad_rot_angle = 15; + if (U.pad_rot_angle == 0.0f) + U.pad_rot_angle = 15.0f; /* graph editor - unselected F-Curve visibility */ if (U.fcu_inactive_alpha == 0) { @@ -2351,7 +2360,7 @@ void init_userdef_do_versions(void) 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); /* Grey (mix between fg/bg) */ + rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Gray (mix between fg/bg) */ } } @@ -2602,7 +2611,22 @@ void init_userdef_do_versions(void) cp[3] = 255; } } - + + if (U.versionfile < 274 || (U.versionfile == 274 && U.subversionfile < 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 (U.versionfile < 275 || (U.versionfile == 275 && U.subversionfile < 1)) { + bTheme *btheme; + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + copy_v4_v4_char(btheme->tclip.metadatatext, btheme->tseq.text_hi); + } + } + if (U.pixelsize == 0.0f) U.pixelsize = 1.0f; diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index b4a120b2dea..4f4b5ab07ff 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -99,11 +99,12 @@ BLI_INLINE void clamp_rctf_to_rcti(rcti *dst, const rctf *src) /* XXX still unresolved: scrolls hide/unhide vs region mask handling */ /* XXX there's V2D_SCROLL_HORIZONTAL_HIDE and V2D_SCROLL_HORIZONTAL_FULLR ... */ -/* helper to allow scrollbars to dynamically hide - * - returns a copy of the scrollbar settings with the flags to display - * horizontal/vertical scrollbars removed - * - input scroll value is the v2d->scroll var - * - hide flags are set per region at drawtime +/** + * helper to allow scrollbars to dynamically hide + * - returns a copy of the scrollbar settings with the flags to display + * horizontal/vertical scrollbars removed + * - input scroll value is the v2d->scroll var + * - hide flags are set per region at drawtime */ static int view2d_scroll_mapped(int scroll) { @@ -197,11 +198,12 @@ static void view2d_masks(View2D *v2d, int check_scrollers) /* Refresh and Validation */ -/* Initialize all relevant View2D data (including view rects if first time) and/or refresh mask sizes after view resize - * - for some of these presets, it is expected that the region will have defined some - * additional settings necessary for the customization of the 2D viewport to its requirements - * - this function should only be called from region init() callbacks, where it is expected that - * this is called before UI_view2d_size_update(), as this one checks that the rects are properly initialized. +/** + * Initialize all relevant View2D data (including view rects if first time) and/or refresh mask sizes after view resize + * - for some of these presets, it is expected that the region will have defined some + * additional settings necessary for the customization of the 2D viewport to its requirements + * - this function should only be called from region init() callbacks, where it is expected that + * this is called before UI_view2d_size_update(), as this one checks that the rects are properly initialized. */ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) { @@ -320,7 +322,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) if (do_init) { float panelzoom = (style) ? style->panelzoom : 1.0f; - float scrolw = v2d->scroll & V2D_SCROLL_RIGHT ? V2D_SCROLL_WIDTH : 0.0f; + float scrolw = (v2d->scroll & V2D_SCROLL_RIGHT) ? V2D_SCROLL_WIDTH : 0.0f; v2d->tot.xmin = 0.0f; v2d->tot.xmax = winx - scrolw; @@ -361,8 +363,9 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) } -/* Ensure View2D rects remain in a viable configuration - * - cur is not allowed to be: larger than max, smaller than min, or outside of tot +/** + * Ensure View2D rects remain in a viable configuration + * 'cur' is not allowed to be: larger than max, smaller than min, or outside of 'tot' */ // XXX pre2.5 -> this used to be called test_view2d() static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_scrollers) @@ -842,7 +845,8 @@ void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag) } -/* Restore 'cur' rect to standard orientation (i.e. optimal maximum view of tot) +/** + * Restore 'cur' rect to standard orientation (i.e. optimal maximum view of tot) * This does not take into account if zooming the view on an axis will improve the view (if allowed) */ void UI_view2d_curRect_reset(View2D *v2d) @@ -1098,8 +1102,10 @@ void UI_view2d_view_ortho(View2D *v2d) glLoadIdentity(); } -/* Set view matrices to only use one axis of 'cur' only - * - xaxis = if non-zero, only use cur x-axis, otherwise use cur-yaxis (mostly this will be used for x) +/** + * Set view matrices to only use one axis of 'cur' only + * + * \param xaxis: if non-zero, only use cur x-axis, otherwise use cur-yaxis (mostly this will be used for x) */ void UI_view2d_view_orthoSpecial(ARegion *ar, View2D *v2d, const bool xaxis) { @@ -1192,20 +1198,23 @@ static void step_to_grid(float *step, int *power, int unit) } } -/* Initialize settings necessary for drawing gridlines in a 2d-view - * - Currently, will return pointer to View2DGrid struct that needs to - * be freed with UI_view2d_grid_free() - * - Is used for scrollbar drawing too (for units drawing) - * - Units + clamping args will be checked, to make sure they are valid values that can be used - * so it is very possible that we won't return grid at all! - * - * - xunits,yunits = V2D_UNIT_* grid steps in seconds or frames - * - xclamp,yclamp = V2D_CLAMP_* only show whole-number intervals - * - winx = width of region we're drawing to, note: not used but keeping for completeness. - * - winy = height of region we're drawing into +/** + * Initialize settings necessary for drawing gridlines in a 2d-view + * + * - Currently, will return pointer to View2DGrid struct that needs to + * be freed with UI_view2d_grid_free() + * - Is used for scrollbar drawing too (for units drawing) + * - Units + clamping args will be checked, to make sure they are valid values that can be used + * so it is very possible that we won't return grid at all! + * + * - xunits,yunits = V2D_UNIT_* grid steps in seconds or frames + * - xclamp,yclamp = V2D_CLAMP_* only show whole-number intervals + * - winx = width of region we're drawing to, note: not used but keeping for completeness. + * - winy = height of region we're drawing into */ -View2DGrid *UI_view2d_grid_calc(Scene *scene, View2D *v2d, - short xunits, short xclamp, short yunits, short yclamp, int UNUSED(winx), int winy) +View2DGrid *UI_view2d_grid_calc( + Scene *scene, View2D *v2d, + short xunits, short xclamp, short yunits, short yclamp, int UNUSED(winx), int winy) { View2DGrid *grid; @@ -1483,9 +1492,11 @@ void UI_view2d_grid_free(View2DGrid *grid) /* *********************************************************************** */ /* Scrollers */ -/* View2DScrollers is typedef'd in UI_view2d.h - * WARNING: the start of this struct must not change, as view2d_ops.c uses this too. - * For now, we don't need to have a separate (internal) header for structs like this... +/** + * View2DScrollers is typedef'd in UI_view2d.h + * + * \warning The start of this struct must not change, as view2d_ops.c uses this too. + * For now, we don't need to have a separate (internal) header for structs like this... */ struct View2DScrollers { /* focus bubbles */ @@ -1502,8 +1513,9 @@ struct View2DScrollers { }; /* Calculate relevant scroller properties */ -View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, - short xunits, short xclamp, short yunits, short yclamp) +View2DScrollers *UI_view2d_scrollers_calc( + const bContext *C, View2D *v2d, + short xunits, short xclamp, short yunits, short yclamp) { View2DScrollers *scrollers; rcti vert, hor; @@ -1885,18 +1897,22 @@ void UI_view2d_scrollers_free(View2DScrollers *scrollers) /* *********************************************************************** */ /* List View Utilities */ -/* Get the view-coordinates of the nominated cell - * - columnwidth, rowheight = size of each 'cell' - * - startx, starty = coordinates (in 'tot' rect space) that the list starts from - * This should be (0,0) for most views. However, for those where the starting row was offsetted - * (like for Animation Editor channel lists, to make the first entry more visible), these will be - * the min-coordinates of the first item. - * - column, row = the 2d-coordinates (in 2D-view / 'tot' rect space) the cell exists at - * - rect = coordinates of the cell (passed as single var instead of 4 separate, as it's more useful this way) +/** Get the view-coordinates of the nominated cell + * + * \param columnwidth, rowheight: size of each 'cell' + * \param startx, starty: coordinates (in 'tot' rect space) that the list starts from. + * This should be (0,0) for most views. However, for those where the starting row was offsetted + * (like for Animation Editor channel lists, to make the first entry more visible), these will be + * the min-coordinates of the first item. + * \param column, row: The 2d-coordinates + * (in 2D-view / 'tot' rect space) the cell exists at + * \param rect: coordinates of the cell + * (passed as single var instead of 4 separate, as it's more useful this way) */ -void UI_view2d_listview_cell_to_view(View2D *v2d, float columnwidth, float rowheight, - float startx, float starty, - int column, int row, rctf *rect) +void UI_view2d_listview_cell_to_view( + View2D *v2d, float columnwidth, float rowheight, + float startx, float starty, + int column, int row, rctf *rect) { /* sanity checks */ if (ELEM(NULL, v2d, rect)) { @@ -1930,17 +1946,20 @@ void UI_view2d_listview_cell_to_view(View2D *v2d, float columnwidth, float rowhe } } -/* Get the 'cell' (row, column) that the given 2D-view coordinates (i.e. in 'tot' rect space) lie in. - * - columnwidth, rowheight = size of each 'cell' - * - startx, starty = coordinates (in 'tot' rect space) that the list starts from - * This should be (0,0) for most views. However, for those where the starting row was offsetted - * (like for Animation Editor channel lists, to make the first entry more visible), these will be - * the min-coordinates of the first item. - * - viewx, viewy = 2D-coordinates (in 2D-view / 'tot' rect space) to get the cell for - * - column, row = the 'coordinates' of the relevant 'cell' +/** + * Get the 'cell' (row, column) that the given 2D-view coordinates (i.e. in 'tot' rect space) lie in. + * + * \param columnwidth, rowheight: size of each 'cell' + * \param startx, starty: coordinates (in 'tot' rect space) that the list starts from. + * This should be (0,0) for most views. However, for those where the starting row was offsetted + * (like for Animation Editor channel lists, to make the first entry more visible), these will be + * the min-coordinates of the first item. + * \param viewx, viewy: 2D-coordinates (in 2D-view / 'tot' rect space) to get the cell for + * \param column, row: the 'coordinates' of the relevant 'cell' */ -void UI_view2d_listview_view_to_cell(View2D *v2d, float columnwidth, float rowheight, float startx, float starty, - float viewx, float viewy, int *column, int *row) +void UI_view2d_listview_view_to_cell( + View2D *v2d, float columnwidth, float rowheight, float startx, float starty, + float viewx, float viewy, int *column, int *row) { /* adjust view coordinates to be all positive ints, corrected for the start offset */ const int x = (int)(floorf(fabsf(viewx) + 0.5f) - startx); @@ -1967,13 +1986,16 @@ void UI_view2d_listview_view_to_cell(View2D *v2d, float columnwidth, float rowhe *row = 0; } -/* Get the 'extreme' (min/max) column and row indices which are visible within the 'cur' rect - * - columnwidth, rowheight = size of each 'cell' - * - startx, starty = coordinates that the list starts from, which should be (0,0) for most views - * - column/row_min/max = the starting and ending column/row indices +/** + * Get the 'extreme' (min/max) column and row indices which are visible within the 'cur' rect + * + * \param columnwidth, rowheight: Size of each 'cell' + * \param startx, starty: Coordinates that the list starts from, which should be (0,0) for most views + * \param column_min, column_max, row_min, row_max: The starting and ending column/row indices */ -void UI_view2d_listview_visible_cells(View2D *v2d, float columnwidth, float rowheight, float startx, float starty, - int *column_min, int *column_max, int *row_min, int *row_max) +void UI_view2d_listview_visible_cells( + View2D *v2d, float columnwidth, float rowheight, float startx, float starty, + int *column_min, int *column_max, int *row_min, int *row_max) { /* using 'cur' rect coordinates, call the cell-getting function to get the cells for this */ if (v2d) { @@ -1999,10 +2021,11 @@ float UI_view2d_region_to_view_y(struct View2D *v2d, float y) return (v2d->cur.ymin + (BLI_rctf_size_y(&v2d->cur) * (y - v2d->mask.ymin) / BLI_rcti_size_y(&v2d->mask))); } -/* Convert from screen/region space to 2d-View space - * - * - x,y = coordinates to convert - * - viewx,viewy = resultant coordinates +/** + * Convert from screen/region space to 2d-View space + * + * \param x, y: coordinates to convert + * \param r_view_x, r_view_y: resultant coordinates */ void UI_view2d_region_to_view(View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) { @@ -2030,11 +2053,12 @@ float UI_view2d_view_to_region_y(View2D *v2d, float y) return (v2d->mask.ymin + (((y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur)) * BLI_rcti_size_y(&v2d->mask))); } -/* Convert from 2d-View space to screen/region space - * - Coordinates are clamped to lie within bounds of region +/** + * Convert from 2d-View space to screen/region space + * \note Coordinates are clamped to lie within bounds of region * - * - x,y = coordinates to convert - * - regionx,regiony = resultant coordinates + * \param x, y: Coordinates to convert. + * \param r_region_x, r_region_y: Resultant coordinates. */ bool UI_view2d_view_to_region_clip(View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) { @@ -2057,11 +2081,13 @@ bool UI_view2d_view_to_region_clip(View2D *v2d, float x, float y, int *r_region_ } } -/* Convert from 2d-view space to screen/region space - * - Coordinates are NOT clamped to lie within bounds of region +/** + * Convert from 2d-view space to screen/region space + * + * \note Coordinates are NOT clamped to lie within bounds of region. * - * - x,y = coordinates to convert - * - regionx,regiony = resultant coordinates + * \param x, y: Coordinates to convert. + * \param r_region_x, r_region_y: Resultant coordinates. */ void UI_view2d_view_to_region(View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) { @@ -2175,25 +2201,30 @@ View2D *UI_view2d_fromcontext_rwin(const bContext *C) } -/* Calculate the scale per-axis of the drawing-area - * - Is used to inverse correct drawing of icons, etc. that need to follow view - * but not be affected by scale +/** + * Calculate the scale per-axis of the drawing-area * - * - x,y = scale on each axis + * Is used to inverse correct drawing of icons, etc. that need to follow view + * but not be affected by scale + * + * \param x, y: scale on each axis */ void UI_view2d_scale_get(View2D *v2d, float *x, float *y) { if (x) *x = BLI_rcti_size_x(&v2d->mask) / BLI_rctf_size_x(&v2d->cur); if (y) *y = BLI_rcti_size_y(&v2d->mask) / BLI_rctf_size_y(&v2d->cur); } -/* Same as UI_view2d_scale_get() - 1.0f / x, y */ +/** + * Same as ``UI_view2d_scale_get() - 1.0f / x, y`` + */ void UI_view2d_scale_get_inverse(View2D *v2d, float *x, float *y) { if (x) *x = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); if (y) *y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask); } -/* Simple functions for consistent center offset access. +/** + * Simple functions for consistent center offset access. * Used by node editor to shift view center for each individual node tree. */ void UI_view2d_center_get(struct View2D *v2d, float *x, float *y) @@ -2239,13 +2270,15 @@ void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac) UI_view2d_curRect_validate(v2d); } -/* Check if mouse is within scrollers - * - Returns appropriate code for match - * 'h' = in horizontal scroller - * 'v' = in vertical scroller - * 0 = not in scroller - * - * - x,y = mouse coordinates in screen (not region) space +/** + * Check if mouse is within scrollers + * + * \param x, y: Mouse coordinates in screen (not region) space. + * + * \return appropriate code for match. + * - 'h' = in horizontal scroller. + * - 'v' = in vertical scroller. + * - 0 = not in scroller. */ short UI_view2d_mouse_in_scrollers(const bContext *C, View2D *v2d, int x, int y) { @@ -2288,8 +2321,9 @@ typedef struct View2DString { static MemArena *g_v2d_strings_arena = NULL; static View2DString *g_v2d_strings = NULL; -void UI_view2d_text_cache_add(View2D *v2d, float x, float y, - const char *str, size_t str_len, const char col[4]) +void UI_view2d_text_cache_add( + View2D *v2d, float x, float y, + const char *str, size_t str_len, const char col[4]) { int mval[2]; @@ -2319,8 +2353,9 @@ void UI_view2d_text_cache_add(View2D *v2d, float x, float y, } /* no clip (yet) */ -void UI_view2d_text_cache_add_rectf(View2D *v2d, const rctf *rect_view, - const char *str, size_t str_len, const char col[4]) +void UI_view2d_text_cache_add_rectf( + View2D *v2d, const rctf *rect_view, + const char *str, size_t str_len, const char col[4]) { rcti rect; diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 88140d897ae..6fbe8509188 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -63,12 +63,13 @@ static int view2d_poll(bContext *C) /* ********************************************************* */ /* VIEW PANNING OPERATOR */ -/* This group of operators come in several forms: - * 1) Modal 'dragging' with MMB - where movement of mouse dictates amount to pan view by - * 2) Scrollwheel 'steps' - rolling mousewheel by one step moves view by predefined amount +/** + * This group of operators come in several forms: + * -# Modal 'dragging' with MMB - where movement of mouse dictates amount to pan view by + * -# Scrollwheel 'steps' - rolling mousewheel by one step moves view by predefined amount * - * In order to make sure this works, each operator must define the following RNA-Operator Props: - * deltax, deltay - define how much to move view by (relative to zoom-correction factor) + * In order to make sure this works, each operator must define the following RNA-Operator Props: + * - `deltax, deltay` - define how much to move view by (relative to zoom-correction factor) */ /* ------------------ Shared 'core' stuff ---------------------- */ @@ -328,7 +329,7 @@ static void VIEW2D_OT_pan(wmOperatorType *ot) ot->cancel = view_pan_cancel; /* operator is modal */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; /* rna - must keep these in sync with the other operators */ RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX); @@ -525,15 +526,18 @@ static void VIEW2D_OT_scroll_up(wmOperatorType *ot) /* ********************************************************* */ /* SINGLE-STEP VIEW ZOOMING OPERATOR */ -/* This group of operators come in several forms: - * 1) Scrollwheel 'steps' - rolling mousewheel by one step zooms view by predefined amount - * 2) Scrollwheel 'steps' + alt + ctrl/shift - zooms view on one axis only (ctrl=x, shift=y) // XXX this could be implemented... - * 3) Pad +/- Keys - pressing each key moves the zooms the view by a predefined amount +/** + * This group of operators come in several forms: + * -# Scrollwheel 'steps' - rolling mousewheel by one step zooms view by predefined amount. + * -# Scrollwheel 'steps' + alt + ctrl/shift - zooms view on one axis only (ctrl=x, shift=y). + * XXX this could be implemented... + * -# Pad +/- Keys - pressing each key moves the zooms the view by a predefined amount. * * In order to make sure this works, each operator must define the following RNA-Operator Props: - * zoomfacx, zoomfacy - These two zoom factors allow for non-uniform scaling. - * It is safe to scale by 0, as these factors are used to determine - * amount to enlarge 'cur' by + * + * - zoomfacx, zoomfacy - These two zoom factors allow for non-uniform scaling. + * It is safe to scale by 0, as these factors are used to determine. + * amount to enlarge 'cur' by. */ /* ------------------ 'Shared' stuff ------------------------ */ @@ -620,8 +624,9 @@ static int view_zoom_poll(bContext *C) } /* apply transform to view (i.e. adjust 'cur' rect) */ -static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool use_mousepos, - const float facx, const float facy) +static void view_zoomstep_apply_ex( + bContext *C, v2dViewZoomData *vzd, const bool use_mousepos, + const float facx, const float facy) { ARegion *ar = CTX_wm_region(C); View2D *v2d = &ar->v2d; @@ -661,7 +666,9 @@ static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool const float zoomx = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur); /* only move view to mouse if zoom fac is inside minzoom/maxzoom */ - if (IN_RANGE_INCL(zoomx, v2d->minzoom, v2d->maxzoom)) { + if (((v2d->keepzoom & V2D_LIMITZOOM) == 0) || + IN_RANGE_INCL(zoomx, v2d->minzoom, v2d->maxzoom)) + { float mval_fac = (vzd->mx_2d - cur_old.xmin) / BLI_rctf_size_x(&cur_old); float mval_faci = 1.0f - mval_fac; float ofs = (mval_fac * dx) - (mval_faci * dx); @@ -692,7 +699,9 @@ static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool const float zoomy = (float)(BLI_rcti_size_y(&v2d->mask) + 1) / BLI_rctf_size_y(&v2d->cur); /* only move view to mouse if zoom fac is inside minzoom/maxzoom */ - if (IN_RANGE_INCL(zoomy, v2d->minzoom, v2d->maxzoom)) { + if (((v2d->keepzoom & V2D_LIMITZOOM) == 0) || + IN_RANGE_INCL(zoomy, v2d->minzoom, v2d->maxzoom)) + { float mval_fac = (vzd->my_2d - cur_old.ymin) / BLI_rctf_size_y(&cur_old); float mval_faci = 1.0f - mval_fac; float ofs = (mval_fac * dy) - (mval_faci * dy); @@ -867,10 +876,11 @@ static void VIEW2D_OT_zoom_out(wmOperatorType *ot) /* ********************************************************* */ /* DRAG-ZOOM OPERATOR */ -/* MMB Drag - allows non-uniform scaling by dragging mouse +/** + * MMB Drag - allows non-uniform scaling by dragging mouse * - * In order to make sure this works, each operator must define the following RNA-Operator Props: - * deltax, deltay - amounts to add to each side of the 'cur' rect + * In order to make sure this works, each operator must define the following RNA-Operator Props: + * - `deltax, deltay` - amounts to add to each side of the 'cur' rect */ /* apply transform to view (i.e. adjust 'cur' rect) */ @@ -1175,7 +1185,7 @@ static void VIEW2D_OT_zoom(wmOperatorType *ot) ot->poll = view_zoom_poll; /* operator is repeatable */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; /* rna - must keep these in sync with the other operators */ prop = RNA_def_float(ot->srna, "deltax", 0, -FLT_MAX, FLT_MAX, "Delta X", "", -FLT_MAX, FLT_MAX); @@ -1187,10 +1197,12 @@ static void VIEW2D_OT_zoom(wmOperatorType *ot) /* ********************************************************* */ /* BORDER-ZOOM */ -/* The user defines a rect using standard borderselect tools, and we use this rect to +/** + * The user defines a rect using standard borderselect tools, and we use this rect to * define the new zoom-level of the view in the following ways: - * 1) LEFTMOUSE - zoom in to view - * 2) RIGHTMOUSE - zoom out of view + * + * -# LEFTMOUSE - zoom in to view + * -# RIGHTMOUSE - zoom out of view * * Currently, these key mappings are hardcoded, but it shouldn't be too important to * have custom keymappings for this... @@ -1402,8 +1414,9 @@ static float smooth_view_rect_to_fac(const rctf *rect_a, const rctf *rect_b) /* will start timer if appropriate */ /* the arguments are the desired situation */ -void UI_view2d_smooth_view(bContext *C, ARegion *ar, - const rctf *cur, const int smooth_viewtx) +void UI_view2d_smooth_view( + bContext *C, ARegion *ar, + const rctf *cur, const int smooth_viewtx) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); @@ -1528,13 +1541,14 @@ static void VIEW2D_OT_smoothview(wmOperatorType *ot) /* ********************************************************* */ /* SCROLLERS */ -/* Scrollers should behave in the following ways, when clicked on with LMB (and dragged): - * 1) 'Handles' on end of 'bubble' - when the axis that the scroller represents is zoomable, - * enlarge 'cur' rect on the relevant side - * 2) 'Bubble'/'bar' - just drag, and bar should move with mouse (view pans opposite) +/** + * Scrollers should behave in the following ways, when clicked on with LMB (and dragged): + * -# 'Handles' on end of 'bubble' - when the axis that the scroller represents is zoomable, + * enlarge 'cur' rect on the relevant side. + * -# 'Bubble'/'bar' - just drag, and bar should move with mouse (view pans opposite). * - * In order to make sure this works, each operator must define the following RNA-Operator Props: - * deltax, deltay - define how much to move view by (relative to zoom-correction factor) + * In order to make sure this works, each operator must define the following RNA-Operator Props: + * - `deltax, deltay` - define how much to move view by (relative to zoom-correction factor) */ /* customdata for scroller-invoke data */ @@ -1556,10 +1570,12 @@ typedef struct v2dScrollerMove { } v2dScrollerMove; -/* View2DScrollers is typedef'd in UI_view2d.h +/** + * #View2DScrollers is typedef'd in UI_view2d.h * This is a CUT DOWN VERSION of the 'real' version, which is defined in view2d.c, as we only need focus bubble info - * WARNING: the start of this struct must not change, so that it stays in sync with the 'real' version - * For now, we don't need to have a separate (internal) header for structs like this... + * + * \warning: The start of this struct must not change, so that it stays in sync with the 'real' version + * For now, we don't need to have a separate (internal) header for structs like this... */ struct View2DScrollers { /* focus bubbles */ @@ -1578,10 +1594,12 @@ enum { /* ------------------------ */ -/* check if mouse is within scroller handle - * - mouse = relevant mouse coordinate in region space - * - sc_min, sc_max = extents of scroller 'groove' (potential available space for scroller) - * - sh_min, sh_max = positions of scrollbar handles +/** + * Check if mouse is within scroller handle. + * + * \param mouse: relevant mouse coordinate in region space. + * \param sc_min, sc_max: extents of scroller 'groove' (potential available space for scroller). + * \param sh_min, sh_max: positions of scrollbar handles. */ static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_min, int sh_max) { @@ -1785,7 +1803,10 @@ static void scroller_activate_apply(bContext *C, wmOperator *op) UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); } -/* handle user input for scrollers - calculations of mouse-movement need to be done here, not in the apply callback! */ +/** + * Handle user input for scrollers - calculations of mouse-movement need to be done here, + * not in the apply callback! + */ static int scroller_activate_modal(bContext *C, wmOperator *op, const wmEvent *event) { v2dScrollerMove *vsm = op->customdata; |