UI: multi-drag number button editing
clicking and dragging down edits multiple number buttons at once. (patch D270)
This commit is contained in:
parent
ff0ceb9926
commit
127330d6ca
|
@ -172,6 +172,7 @@ enum {
|
|||
UI_BUT_VEC_SIZE_LOCK = (1 << 22), /* used to flag if color hsv-circle should keep luminance */
|
||||
UI_BUT_COLOR_CUBIC = (1 << 23), /* cubic saturation for the color wheel */
|
||||
UI_BUT_LIST_ITEM = (1 << 24), /* This but is "inside" a list item (currently used to change theme colors). */
|
||||
UI_BUT_DRAG_MULTI = (1 << 25), /* edit this button as well as the active button (not just dragging) */
|
||||
};
|
||||
|
||||
#define UI_PANEL_WIDTH 340
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue