diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2015-06-29 18:10:42 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2015-06-29 18:10:42 +0300 |
commit | 58d6cbba6da31db8dc8a2b42d528b9a353081904 (patch) | |
tree | 04b57a2f809c6f08d84a082edf061f3ece631860 /source/blender/editors/interface/interface_handlers.c | |
parent | 94549adec4b6857fb6ec4cf77606da51ff7c26b7 (diff) | |
parent | 295d0c52a26730edc6d4ed1276e4051cce006be5 (diff) |
Merge branch 'master' into temp-ghash-setopstemp-ghash-setops
Diffstat (limited to 'source/blender/editors/interface/interface_handlers.c')
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 853 |
1 files changed, 659 insertions, 194 deletions
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 71b7b95208b..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; @@ -4644,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; @@ -4705,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; @@ -4763,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; @@ -4783,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; @@ -4928,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; @@ -5025,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; @@ -5286,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) { @@ -5336,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; @@ -5720,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; @@ -5931,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); } @@ -5952,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); } @@ -6001,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); @@ -6070,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); @@ -6217,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); @@ -6229,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); @@ -6252,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 */ @@ -6331,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); @@ -6488,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: @@ -6592,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; + } } } @@ -6731,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; } @@ -6846,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) { @@ -6940,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; @@ -7024,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 */ @@ -7086,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)) { @@ -7131,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 { @@ -7191,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; @@ -7264,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); @@ -7470,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; @@ -7501,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); @@ -7605,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; @@ -7653,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 */ @@ -7814,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; @@ -7964,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) @@ -7999,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]}; @@ -8188,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; @@ -8559,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; @@ -8628,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; @@ -8707,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; @@ -9106,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); @@ -9390,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) @@ -9408,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; |