diff options
author | Campbell Barton <ideasman42@gmail.com> | 2014-02-08 02:34:01 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2014-02-08 02:42:26 +0400 |
commit | 127330d6cadd107d645acd8d97d2f15a75798bf1 (patch) | |
tree | 31cfaef14fb33d7a8e8abc8a09cc9dd5464f410a /source/blender/editors/interface | |
parent | ff0ceb9926d23d1af37c2a09fa90abf28b482556 (diff) |
UI: multi-drag number button editing
clicking and dragging down edits multiple number buttons at once. (patch D270)
Diffstat (limited to 'source/blender/editors/interface')
-rw-r--r-- | source/blender/editors/interface/interface.c | 30 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 373 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_widgets.c | 53 |
4 files changed, 439 insertions, 18 deletions
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 8ad96b4f325..fb0b0351453 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -584,7 +584,7 @@ static void ui_but_update_linklines(uiBlock *block, uiBut *oldbut, uiBut *newbut static bool ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut **but_p, uiBut **but_old_p) { /* flags from the buttons we want to refresh, may want to add more here... */ - const int flag_copy = UI_BUT_REDALERT; + const int flag_copy = UI_BUT_REDALERT | UI_BUT_DRAG_MULTI; const int drawflag_copy = 0; /* None currently. */ uiBlock *oldblock = block->oldblock; @@ -676,6 +676,8 @@ static bool ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBu /* note: if layout hasn't been applied yet, it uses old button pointers... */ } else { + but->flag = (but->flag & ~flag_copy) | (oldbut->flag & flag_copy); + /* ensures one button can get activated, and in case the buttons * draw are the same this gives O(1) lookup for each button */ BLI_remlink(&oldblock->buttons, oldbut); @@ -1577,6 +1579,32 @@ bool ui_is_but_unit(const uiBut *but) return true; } +/** + * Check if this button is similar enough to be grouped with another. + */ +bool ui_is_but_compatible(const uiBut *but_a, const uiBut *but_b) +{ + if (but_a->type != but_b->type) + return false; + if (but_a->pointype != but_b->pointype) + return false; + + if (but_a->rnaprop) { + if (but_a->rnapoin.type != but_b->rnapoin.type) + return false; + if (but_a->rnapoin.data != but_b->rnapoin.data) + return false; + if (but_a->rnapoin.id.data != but_b->rnapoin.id.data) + return false; + if (RNA_property_type(but_a->rnaprop) != RNA_property_type(but_b->rnaprop)) + return false; + if (RNA_property_subtype(but_a->rnaprop) != RNA_property_subtype(but_b->rnaprop)) + return false; + } + + return true; +} + bool ui_is_but_rna_valid(uiBut *but) { if (but->rnaprop == NULL || RNA_struct_contains_property(&but->rnapoin, but->rnaprop)) { diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 625e38e3d00..f189af751b4 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -47,7 +47,11 @@ #include "DNA_screen_types.h" #include "BLI_math.h" -#include "BLI_blenlib.h" +#include "BLI_listbase.h" +#include "BLI_linklist.h" +#include "BLI_string.h" +#include "BLI_string_utf8.h" +#include "BLI_rect.h" #include "BLI_utildefines.h" #include "BLI_string_cursor_utf8.h" @@ -86,6 +90,9 @@ /* support dragging toggle buttons */ #define USE_DRAG_TOGGLE +/* support dragging multiple number buttons at once */ +#define USE_DRAG_MULTINUM + /* so we can avoid very small mouse-moves from jumping away from keyboard navigation [#34936] */ #define USE_KEYNAV_LIMIT @@ -134,6 +141,59 @@ typedef enum uiHandleButtonState { BUTTON_STATE_EXIT } uiHandleButtonState; + +#ifdef USE_DRAG_MULTINUM + +/* 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 checkign 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) + * 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) + + +/* a simple version of uiHandleButtonData when accessing multiple buttons */ +typedef struct uiButMultiState { + double origvalue; + uiBut *but; +} uiButMultiState; + +typedef struct uiHandleButtonMulti { + enum { + BUTTON_MULTI_INIT_UNSET = 0, /* gesture direction unknown, wait until mouse has moved enough... */ + BUTTON_MULTI_INIT_SETUP, /* vertical gesture detected, flag buttons interactively (UI_BUT_DRAG_MULTI) */ + BUTTON_MULTI_INIT_ENABLE, /* flag buttons finished, apply horizontal motion to active and flagged */ + BUTTON_MULTI_INIT_DISABLE, /* vertical gesture _not_ detected, take no further action */ + } init; + + bool has_mbuts; /* any buttons flagged UI_BUT_DRAG_MULTI */ + LinkNode *mbuts; + uiButStore *bs_mbuts; + + /* before activating, we need to check gesture direction + * accumulate signed cursor movement here so we can tell if this is a vertical motion or not. */ + float drag_dir[2]; + + /* values copied direct from event->x,y + * used to detect buttons between the current and initial mouse position */ + int drag_start[2]; + + /* store x location once BUTTON_MULTI_INIT_SETUP is set, + * moving outside this sets BUTTON_MULTI_INIT_ENABLE */ + int drag_lock_x; + +} uiHandleButtonMulti; + +#endif /* USE_DRAG_MULTINUM */ + + + typedef struct uiHandleButtonData { wmWindowManager *wm; wmWindow *window; @@ -197,6 +257,11 @@ typedef struct uiHandleButtonData { struct uiKeyNavLock searchbox_keynav_state; #endif +#ifdef USE_DRAG_MULTINUM + /* Multi-buttons will be updated in unison with the active button. */ + uiHandleButtonMulti multi_data; +#endif + /* post activate */ uiButtonActivateType posttype; uiBut *postbut; @@ -251,6 +316,11 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *userd 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 uiButMultiState *ui_multibut_lookup(uiHandleButtonData *data, const uiBut *but); +#endif + /* buttons clipboard */ static ColorBand but_copypaste_coba = {0}; static CurveMapping but_copypaste_curve = {0}; @@ -736,6 +806,182 @@ static void ui_apply_but_CURVE(bContext *C, uiBut *but, uiHandleButtonData *data /* ****************** drag drop code *********************** */ + +#ifdef USE_DRAG_MULTINUM + +/* small multi-but api */ +static void ui_multibut_add(uiHandleButtonData *data, uiBut *but) +{ + uiButMultiState *mbut_state; + + BLI_assert(but->flag & UI_BUT_DRAG_MULTI); + BLI_assert(data->multi_data.has_mbuts); + + + mbut_state = MEM_callocN(sizeof(*mbut_state), __func__); + mbut_state->but = but; + mbut_state->origvalue = ui_get_but_val(but); + + BLI_linklist_prepend(&data->multi_data.mbuts, mbut_state); + + UI_butstore_register(data->multi_data.bs_mbuts, &mbut_state->but); +} + +static uiButMultiState *ui_multibut_lookup(uiHandleButtonData *data, const uiBut *but) +{ + LinkNode *l; + + for (l = data->multi_data.mbuts; l; l = l->next) { + uiButMultiState *mbut_state; + + mbut_state = l->link; + + if (mbut_state->but == but) { + return mbut_state; + } + } + + return NULL; +} + +static void ui_multibut_restore(uiHandleButtonData *data, uiBlock *block) +{ + uiBut *but; + + for (but = block->buttons.first; but; but = but->next) { + if (but->flag & UI_BUT_DRAG_MULTI) { + uiButMultiState *mbut_state = ui_multibut_lookup(data, but); + if (mbut_state) { + ui_set_but_val(but, mbut_state->origvalue); + } + } + } +} + +static void ui_multibut_free(uiHandleButtonData *data, uiBlock *block) +{ + BLI_linklist_freeN(data->multi_data.mbuts); + data->multi_data.mbuts = NULL; + + if (data->multi_data.bs_mbuts) { + UI_butstore_free(block, data->multi_data.bs_mbuts); + data->multi_data.bs_mbuts = NULL; + } +} + +static bool ui_multibut_states_tag(uiBut *but_active, uiHandleButtonData *data, const wmEvent *event) +{ + uiBut *but; + float seg[2][2]; + bool changed = false; + + seg[0][0] = data->multi_data.drag_start[0]; + seg[0][1] = data->multi_data.drag_start[1]; + + seg[1][0] = event->x; + seg[1][1] = event->y; + + BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_SETUP); + + ui_window_to_block_fl(data->region, but_active->block, &seg[0][0], &seg[0][1]); + ui_window_to_block_fl(data->region, but_active->block, &seg[1][0], &seg[1][1]); + + data->multi_data.has_mbuts = false; + + /* follow ui_but_find_mouse_over_ex logic */ + for (but = but_active->block->buttons.first; but; but = but->next) { + bool drag_prev = false; + bool drag_curr = false; + + /* re-set each time */ + if (but->flag & UI_BUT_DRAG_MULTI) { + but->flag &= ~UI_BUT_DRAG_MULTI; + drag_prev = true; + } + + if (ui_is_but_interactive(but, false)) { + + /* drag checks */ + if (but_active != but) { + if (ui_is_but_compatible(but_active, but)) { + + BLI_assert(but->active == NULL); + + /* finally check for overlap */ + if (BLI_rctf_isect_segment(&but->rect, seg[0], seg[1])) { + + but->flag |= UI_BUT_DRAG_MULTI; + data->multi_data.has_mbuts = true; + drag_curr = true; + } + } + } + } + + changed |= (drag_prev != drag_curr); + } + + return changed; +} + +static void ui_multibut_states_create(uiBut *but_active, uiHandleButtonData *data) +{ + uiBut *but; + + BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_SETUP); + + data->multi_data.bs_mbuts = UI_butstore_create(but_active->block); + + for (but = but_active->block->buttons.first; but; but = but->next) { + if (but->flag & UI_BUT_DRAG_MULTI) { + ui_multibut_add(data, but); + } + } +} + +static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBlock *block) +{ + ARegion *ar = data->region; + const double value_delta = data->value - data->origvalue; + uiBut *but; + + BLI_assert(data->multi_data.init == BUTTON_MULTI_INIT_ENABLE); + + for (but = block->buttons.first; but; but = but->next) { + if (but->flag & UI_BUT_DRAG_MULTI) { + /* mbut_states for delta */ + uiButMultiState *mbut_state = ui_multibut_lookup(data, but); + + if (mbut_state) { + void *active_back; + + ui_button_execute_begin(C, ar, but, &active_back); + BLI_assert(active_back == NULL); + /* no need to check 'data->state' here */ + if (data->str) { + /* entering text (set all) */ + but->active->value = data->value; + ui_set_but_string(C, but, data->str); + } + else { + /* dragging (use delta) */ + but->active->value = mbut_state->origvalue + value_delta; + } + ui_button_execute_end(C, ar, but, active_back); + } + else { + /* highly unlikely */ + printf("%s: cant find button\n", __func__); + } + /* end */ + + } + } +} + +#endif /* USE_DRAG_MULTINUM */ + + #ifdef USE_DRAG_TOGGLE typedef struct uiDragToggleHandle { @@ -1354,6 +1600,19 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut break; } +#ifdef USE_DRAG_MULTINUM + if (data->multi_data.has_mbuts) { + if (data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) { + if (data->cancel) { + ui_multibut_restore(data, block); + } + else { + ui_multibut_states_apply(C, data, block); + } + } + } +#endif + but->editstr = editstr; but->editval = editval; but->editvec = editvec; @@ -3184,6 +3443,10 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton button_activate_state(C, but, BUTTON_STATE_EXIT); retval = WM_UI_HANDLER_BREAK; } + +#ifdef USE_DRAG_MULTINUM + copy_v2_v2_int(data->multi_data.drag_start, &event->x); +#endif } } @@ -3205,12 +3468,24 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton const enum eSnapType snap = ui_event_to_snap(event); float fac; +#ifdef USE_DRAG_MULTINUM + data->multi_data.drag_dir[0] += fabsf(data->draglastx - mx); + data->multi_data.drag_dir[1] += fabsf(data->draglasty - my); +#endif + fac = 1.0f; if (event->shift) fac /= 10.0f; if (event->alt) fac /= 20.0f; if (ui_numedit_but_NUM(but, data, (ui_is_a_warp_but(but) ? screen_mx : mx), snap, fac)) ui_numedit_apply(C, block, but, data); +#ifdef USE_DRAG_MULTINUM + else if (data->multi_data.has_mbuts) { + if (data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) { + ui_multibut_states_apply(C, data, block); + } + } +#endif } retval = WM_UI_HANDLER_BREAK; } @@ -3286,6 +3561,9 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton retval = WM_UI_HANDLER_BREAK; } + data->draglastx = mx; + data->draglasty = my; + return retval; } @@ -3451,6 +3729,9 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton retval = WM_UI_HANDLER_BREAK; } } +#ifdef USE_DRAG_MULTINUM + copy_v2_v2_int(data->multi_data.drag_start, &event->x); +#endif } else if (data->state == BUTTON_STATE_NUM_EDITING) { if (event->type == ESCKEY || event->type == RIGHTMOUSE) { @@ -3467,8 +3748,20 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton click = 1; } else if (event->type == MOUSEMOVE) { +#ifdef USE_DRAG_MULTINUM + data->multi_data.drag_dir[0] += fabsf(data->draglastx - mx); + data->multi_data.drag_dir[1] += fabsf(data->draglasty - my); +#endif if (ui_numedit_but_SLI(but, data, mx, true, event->ctrl != 0, event->shift != 0)) ui_numedit_apply(C, block, but, data); + +#ifdef USE_DRAG_MULTINUM + else if (data->multi_data.has_mbuts) { + if (data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) { + ui_multibut_states_apply(C, data, block); + } + } +#endif } retval = WM_UI_HANDLER_BREAK; } @@ -3536,6 +3829,9 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton retval = WM_UI_HANDLER_BREAK; } } + + data->draglastx = mx; + data->draglasty = my; return retval; } @@ -5872,6 +6168,60 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * } } +#ifdef USE_DRAG_MULTINUM + if (data) { + if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || + /* if we started dragging, progress on any event */ + (data->multi_data.init == BUTTON_MULTI_INIT_SETUP)) + { + if (ELEM(but->type, NUM, NUMSLI) && + ELEM(data->state, BUTTON_STATE_TEXT_EDITING, BUTTON_STATE_NUM_EDITING)) + { + /* initialize! */ + if (data->multi_data.init == BUTTON_MULTI_INIT_UNSET) { + /* --> (BUTTON_MULTI_INIT_SETUP | BUTTON_MULTI_INIT_DISABLE) */ + + const float margin_y = DRAG_MULTINUM_THRESHOLD_DRAG_Y / sqrtf(block->aspect); + + /* check if we have a vertical gesture */ + if (len_squared_v2(data->multi_data.drag_dir) > (margin_y * margin_y)) { + const float dir_nor_y[2] = {0.0, 1.0f}; + float dir_nor_drag[2]; + + normalize_v2_v2(dir_nor_drag, data->multi_data.drag_dir); + + if (fabsf(dot_v2v2(dir_nor_drag, dir_nor_y)) > DRAG_MULTINUM_THRESHOLD_VERTICAL) { + data->multi_data.init = BUTTON_MULTI_INIT_SETUP; + data->multi_data.drag_lock_x = event->x; + } + else { + data->multi_data.init = BUTTON_MULTI_INIT_DISABLE; + } + } + } + else if (data->multi_data.init == BUTTON_MULTI_INIT_SETUP) { + /* --> (BUTTON_MULTI_INIT_ENABLE) */ + const float margin_x = DRAG_MULTINUM_THRESHOLD_DRAG_X / sqrtf(block->aspect); + /* check if we're dont setting buttons */ + if ((data->str && ELEM(data->state, BUTTON_STATE_TEXT_EDITING, BUTTON_STATE_NUM_EDITING)) || + ((abs(data->multi_data.drag_lock_x - event->x) > margin_x) && + /* 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.init == BUTTON_MULTI_INIT_SETUP) { + if (ui_multibut_states_tag(but, data, event)) { + ED_region_tag_redraw(data->region); + } + } + } + } + } +#endif /* USE_DRAG_MULTINUM */ return retval; } @@ -6366,6 +6716,22 @@ static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *da if (!onfree) ui_apply_button(C, block, but, data, false); +#ifdef USE_DRAG_MULTINUM + if (data->multi_data.has_mbuts) { + for (bt = block->buttons.first; bt; bt = bt->next) { + if (bt->flag & UI_BUT_DRAG_MULTI) { + bt->flag &= ~UI_BUT_DRAG_MULTI; + + if (!data->cancel) { + ui_apply_autokey(C, bt); + } + } + } + + ui_multibut_free(data, block); + } +#endif + /* if this button is in a menu, this will set the button return * value to the button value and the menu return value to ok, the * menu return value will be picked up and the menu will close */ @@ -6677,8 +7043,9 @@ void ui_button_execute_end(struct bContext *C, struct ARegion *UNUSED(ar), uiBut { ui_apply_button(C, but->block, but, but->active, true); - ui_apply_autokey(C, but); - + if ((but->flag & UI_BUT_DRAG_MULTI) == 0) { + ui_apply_autokey(C, but); + } /* use onfree event so undo is handled by caller and apply is already done above */ button_activate_exit((bContext *)C, but, but->active, false, true); but->active = active_back; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 928ad8a4466..80190675a0a 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -402,6 +402,7 @@ extern void ui_check_but(uiBut *but); extern bool ui_is_but_float(const uiBut *but) ATTR_WARN_UNUSED_RESULT; extern bool ui_is_but_bool(const uiBut *but) ATTR_WARN_UNUSED_RESULT; extern bool ui_is_but_unit(const uiBut *but) ATTR_WARN_UNUSED_RESULT; +extern bool ui_is_but_compatible(const uiBut *but_a, const uiBut *but_b) ATTR_WARN_UNUSED_RESULT; extern bool ui_is_but_rna_valid(uiBut *but) ATTR_WARN_UNUSED_RESULT; extern bool ui_is_but_utf8(const uiBut *but) ATTR_WARN_UNUSED_RESULT; extern bool ui_is_but_search_unlink_visible(const uiBut *but) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 0006163c48e..43b2c68d6c1 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1193,7 +1193,8 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect) { int drawstr_left_len = UI_MAX_DRAW_STR; - char *drawstr_right = NULL; + const char *drawstr = but->drawstr; + const char *drawstr_right = NULL; bool use_right_only = false; uiStyleFontSet(fstyle); @@ -1208,6 +1209,21 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b if (fstyle->kerning == 1) /* for BLF_width */ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + + /* Special case: when we're entering text for multiple buttons, + * don't draw the text for any of the multi-editing buttons */ + if (UNLIKELY(but->flag & UI_BUT_DRAG_MULTI)) { + uiBut *but_iter; + for (but_iter = but->block->buttons.first; but_iter; but_iter = but_iter->next) { + if (but_iter->editstr) { + drawstr = but_iter->editstr; + fstyle->align = UI_STYLE_TEXT_LEFT; + break; + } + } + } + + /* text button selection and cursor */ if (but->editstr && but->pos != -1) { short t = 0, pos = 0; @@ -1218,16 +1234,16 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b selsta_tmp = but->selsta; selend_tmp = but->selend; - if (but->drawstr[0] != 0) { + if (drawstr[0] != 0) { if (but->selsta >= but->ofs) { - selsta_draw = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, selsta_tmp - but->ofs); + selsta_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, selsta_tmp - but->ofs); } else { selsta_draw = 0; } - selwidth_draw = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, selend_tmp - but->ofs); + selwidth_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, selend_tmp - but->ofs); glColor4ubv((unsigned char *)wcol->item); glRects(rect->xmin + selsta_draw, rect->ymin + 2, rect->xmin + selwidth_draw, rect->ymax - 2); @@ -1237,8 +1253,8 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b /* text cursor */ pos = but->pos; if (pos >= but->ofs) { - if (but->drawstr[0] != 0) { - t = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, pos - but->ofs) / but->aspect; + if (drawstr[0] != 0) { + t = BLF_width(fstyle->uifont_id, drawstr + but->ofs, pos - but->ofs) / but->aspect; } glColor3f(0.20, 0.6, 0.9); @@ -1258,20 +1274,23 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b /* cut string in 2 parts - only for menu entries */ if ((but->block->flag & UI_BLOCK_LOOP)) { if (ELEM3(but->type, NUM, TEX, NUMSLI) == 0) { - drawstr_right = strchr(but->drawstr, UI_SEP_CHAR); + drawstr_right = strchr(drawstr, UI_SEP_CHAR); if (drawstr_right) { - drawstr_left_len = (drawstr_right - but->drawstr); + drawstr_left_len = (drawstr_right - drawstr); drawstr_right++; } } } #ifdef USE_NUMBUTS_LR_ALIGN - if (!drawstr_right && ELEM(but->type, NUM, NUMSLI) && (but->editstr == NULL)) { - drawstr_right = strchr(but->drawstr + but->ofs, ':'); + if (!drawstr_right && ELEM(but->type, NUM, NUMSLI) && + /* if we're editing or multi-drag (fake editing), then use left alignment */ + (but->editstr == NULL) && (drawstr == but->drawstr)) + { + drawstr_right = strchr(drawstr + but->ofs, ':'); if (drawstr_right) { drawstr_right++; - drawstr_left_len = (drawstr_right - but->drawstr); + drawstr_left_len = (drawstr_right - drawstr); while (*drawstr_right == ' ') { drawstr_right++; @@ -1279,7 +1298,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b } else { /* no prefix, even so use only cpoin */ - drawstr_right = but->drawstr + but->ofs; + drawstr_right = drawstr + but->ofs; use_right_only = true; } } @@ -1291,14 +1310,14 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b /* for underline drawing */ float font_xofs, font_yofs; - uiStyleFontDrawExt(fstyle, rect, but->drawstr + but->ofs, + uiStyleFontDrawExt(fstyle, rect, drawstr + but->ofs, drawstr_left_len - but->ofs, &font_xofs, &font_yofs); if (but->menu_key != '\0') { char fixedbuf[128]; char *str; - BLI_strncpy(fixedbuf, but->drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawstr_left_len)); + BLI_strncpy(fixedbuf, drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawstr_left_len)); str = strchr(fixedbuf, but->menu_key - 32); /* upper case */ if (str == NULL) @@ -1777,6 +1796,12 @@ static void widget_state(uiWidgetType *wt, int state) char red[4] = {255, 0, 0}; widget_state_blend(wt->wcol.inner, red, 0.4f); } + + if (state & UI_BUT_DRAG_MULTI) { + /* the button isn't SELECT but we're editing this so draw with sel color */ + widget_state_blend(wt->wcol.inner, wt->wcol.inner_sel, 1.0f); + } + if (state & UI_BUT_NODE_ACTIVE) { char blue[4] = {86, 128, 194}; widget_state_blend(wt->wcol.inner, blue, 0.3f); |