Experimental option to allow moving the mouse outside the view, "Continuous Grab" in the user-prefs.

- Useful for dragging buttons to the far right when theyd otherwise hit the screen edge.
- Useful for transform though probably NOT what you want when using the transform manipulator (should make an option).
- When enabled, number buttons use this as well as a different conversion of mouse movement
  float numbuts: mouse 1px == 1-clickstep
  int numbuts: 2px == 1 (tried 1:1 but its too jitter prone)

details...
- access as an option to GHOST_SetCursorGrab(grab, warp)
- Currently all operators that grab use this, could be made an operator flag
- only Ghost/X11 supported currently
This commit is contained in:
Campbell Barton
2009-10-07 07:11:10 +00:00
parent 828395744a
commit 77476b294f
15 changed files with 268 additions and 89 deletions

View File

@@ -230,6 +230,15 @@ static uiBut *ui_but_last(uiBlock *block)
return NULL;
}
static int ui_is_a_warp_but(uiBut *but)
{
if(U.uiflag & USER_CONTINUOUS_MOUSE)
if(ELEM(but->type, NUM, NUMABS))
return TRUE;
return FALSE;
}
/* ********************** button apply/revert ************************/
static ListBase UIAfterFuncs = {NULL, NULL};
@@ -1971,6 +1980,51 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, wmE
return WM_UI_HANDLER_CONTINUE;
}
/* var names match ui_numedit_but_NUM */
static float ui_numedit_apply_snapf(float tempf, float softmin, float softmax, float softrange, int snap)
{
if(tempf==softmin || tempf==softmax)
return tempf;
switch(snap) {
case 0:
break;
case 1:
if(tempf==softmin || tempf==softmax) { }
else if(softrange < 2.10) tempf= 0.1*floor(10*tempf);
else if(softrange < 21.0) tempf= floor(tempf);
else tempf= 10.0*floor(tempf/10.0);
break;
case 2:
if(tempf==softmin || tempf==softmax) { }
else if(softrange < 2.10) tempf= 0.01*floor(100.0*tempf);
else if(softrange < 21.0) tempf= 0.1*floor(10.0*tempf);
else tempf= floor(tempf);
break;
}
return tempf;
}
static float ui_numedit_apply_snap(int temp, float softmin, float softmax, int snap)
{
if(temp==softmin || temp==softmax)
return temp;
switch(snap) {
case 0:
break;
case 1:
temp= 10*(temp/10);
break;
case 2:
temp= 100*(temp/100);
break;
}
return temp;
}
static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, int snap, int mx)
{
float deler, tempf, softmin, softmax, softrange;
@@ -1993,74 +2047,88 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
softmax= but->softmax;
softrange= softmax - softmin;
deler= 500;
if(!ui_is_but_float(but)) {
if((softrange)<100) deler= 200.0;
if((softrange)<25) deler= 50.0;
}
deler /= fac;
if(ui_is_but_float(but) && softrange > 11) {
/* non linear change in mouse input- good for high precicsion */
data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.002);
} else if (!ui_is_but_float(but) && softrange > 129) { /* only scale large int buttons */
/* non linear change in mouse input- good for high precicsionm ints need less fine tuning */
data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.004);
} else {
/*no scaling */
data->dragf+= ((float)(mx-data->draglastx))/deler ;
}
if(ui_is_a_warp_but(but)) {
/* Mouse location isn't screen clamped to the screen so use a linear mapping
* 2px == 1-int, or 1px == 1-ClickStep */
if(ui_is_but_float(but)) {
tempf = data->startvalue + ((mx - data->dragstartx) * fac * 0.01*but->a1);
tempf= ui_numedit_apply_snapf(tempf, softmin, softmax, softrange, snap);
CLAMP(tempf, softmin, softmax);
if(data->dragf>1.0) data->dragf= 1.0;
if(data->dragf<0.0) data->dragf= 0.0;
data->draglastx= mx;
tempf= (softmin + data->dragf*softrange);
if(!ui_is_but_float(but)) {
temp= floor(tempf+.5);
if(tempf==softmin || tempf==softmax);
else if(snap) {
if(snap == 2) temp= 100*(temp/100);
else temp= 10*(temp/10);
if(tempf != data->value) {
data->dragchange= 1;
data->value= tempf;
changed= 1;
}
}
else {
temp= data->startvalue + (mx - data->dragstartx)/2; /* simple 2px == 1 */
temp= ui_numedit_apply_snap(temp, softmin, softmax, snap);
CLAMP(temp, softmin, softmax);
CLAMP(temp, softmin, softmax);
lvalue= (int)data->value;
if(temp != lvalue) {
data->dragchange= 1;
data->value= (double)temp;
changed= 1;
if(temp != data->value) {
data->dragchange= 1;
data->value= temp;
changed= 1;
}
}
}
else {
temp= 0;
/* Use a non-linear mapping of the mouse drag especially for large floats (normal behavior) */
deler= 500;
if(!ui_is_but_float(but)) {
if((softrange)<100) deler= 200.0;
if((softrange)<25) deler= 50.0;
}
deler /= fac;
if(snap) {
if(snap == 2) {
if(tempf==softmin || tempf==softmax);
else if(softrange < 2.10) tempf= 0.01*floor(100.0*tempf);
else if(softrange < 21.0) tempf= 0.1*floor(10.0*tempf);
else tempf= floor(tempf);
}
else {
if(tempf==softmin || tempf==softmax);
else if(softrange < 2.10) tempf= 0.1*floor(10*tempf);
else if(softrange < 21.0) tempf= floor(tempf);
else tempf= 10.0*floor(tempf/10.0);
if(ui_is_but_float(but) && softrange > 11) {
/* non linear change in mouse input- good for high precicsion */
data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.002);
} else if (!ui_is_but_float(but) && softrange > 129) { /* only scale large int buttons */
/* non linear change in mouse input- good for high precicsionm ints need less fine tuning */
data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.004);
} else {
/*no scaling */
data->dragf+= ((float)(mx-data->draglastx))/deler ;
}
if(data->dragf>1.0) data->dragf= 1.0;
if(data->dragf<0.0) data->dragf= 0.0;
data->draglastx= mx;
tempf= (softmin + data->dragf*softrange);
if(!ui_is_but_float(but)) {
temp= floor(tempf+.5);
temp= ui_numedit_apply_snap(temp, softmin, softmax, snap);
CLAMP(temp, softmin, softmax);
lvalue= (int)data->value;
if(temp != lvalue) {
data->dragchange= 1;
data->value= (double)temp;
changed= 1;
}
}
else {
temp= 0;
tempf= ui_numedit_apply_snapf(tempf, softmin, softmax, softrange, snap);
CLAMP(tempf, softmin, softmax);
CLAMP(tempf, softmin, softmax);
if(tempf != data->value) {
data->dragchange= 1;
data->value= tempf;
changed= 1;
if(tempf != data->value) {
data->dragchange= 1;
data->value= tempf;
changed= 1;
}
}
}
return changed;
}
@@ -2071,7 +2139,10 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
mx= event->x;
my= event->y;
ui_window_to_block(data->region, block, &mx, &my);
if(!ui_is_a_warp_but(but)) {
ui_window_to_block(data->region, block, &mx, &my);
}
if(data->state == BUTTON_STATE_HIGHLIGHT) {
/* XXX hardcoded keymap check.... */
@@ -3636,11 +3707,15 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
ui_textedit_end(C, but, data);
/* number editing */
if(state == BUTTON_STATE_NUM_EDITING)
if(state == BUTTON_STATE_NUM_EDITING) {
if(ui_is_a_warp_but(but))
WM_cursor_grab(CTX_wm_window(C), 1, 1);
ui_numedit_begin(but, data);
else if(data->state == BUTTON_STATE_NUM_EDITING)
} else if(data->state == BUTTON_STATE_NUM_EDITING) {
ui_numedit_end(but, data);
if(ui_is_a_warp_but(but))
WM_cursor_grab(CTX_wm_window(C), 0, -1);
}
/* menu open */
if(state == BUTTON_STATE_MENU_OPEN)
ui_blockopen_begin(C, but, data);

View File

@@ -402,6 +402,7 @@ extern UserDef U; /* from blenkernel blender.c */
#define USER_SHOW_FPS (1 << 21)
#define USER_MMB_PASTE (1 << 22)
#define USER_MENUFIXEDORDER (1 << 23)
#define USER_CONTINUOUS_MOUSE (1 << 24)
/* Auto-Keying mode */
/* AUTOKEY_ON is a bitflag */

View File

@@ -1655,6 +1655,10 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_property_boolean_negative_sdna(prop, NULL, "uiflag", USER_MENUFIXEDORDER);
RNA_def_property_ui_text(prop, "Contents Follow Opening Direction", "Otherwise menus, etc will always be top to bottom, left to right, no matter opening direction.");
prop= RNA_def_property(srna, "continuous_mouse", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_CONTINUOUS_MOUSE);
RNA_def_property_ui_text(prop, "Contents Follow Opening Direction", "Otherwise menus, etc will always be top to bottom, left to right, no matter opening direction.");
prop= RNA_def_property(srna, "global_pivot", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_LOCKAROUND);
RNA_def_property_ui_text(prop, "Global Pivot", "Lock the same rotation/scaling pivot in all 3D Views.");

View File

@@ -75,7 +75,7 @@ void WM_cursor_set (struct wmWindow *win, int curs);
void WM_cursor_modal (struct wmWindow *win, int curs);
void WM_cursor_restore (struct wmWindow *win);
void WM_cursor_wait (int val);
void WM_cursor_grab (struct wmWindow *win, int val);
void WM_cursor_grab (struct wmWindow *win, int val, int warp);
void WM_timecursor (struct wmWindow *win, int nr);
void *WM_paint_cursor_activate(struct wmWindowManager *wm, int (*poll)(struct bContext *C), void (*draw)(struct bContext *C, int, int, void *customdata), void *customdata);

View File

@@ -163,10 +163,10 @@ void WM_cursor_wait(int val)
}
}
void WM_cursor_grab(wmWindow *win, int val)
void WM_cursor_grab(wmWindow *win, int val, int warp)
{
if(win)
GHOST_SetCursorGrab(win->ghostwin, val);
GHOST_SetCursorGrab(win->ghostwin, val, warp);
}
/* afer this you can call restore too */

View File

@@ -442,7 +442,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P
else if(retval & OPERATOR_RUNNING_MODAL) {
/* grab cursor during blocking modal ops (X11) */
if(ot->flag & OPTYPE_BLOCKING)
WM_cursor_grab(CTX_wm_window(C), 1);
WM_cursor_grab(CTX_wm_window(C), 1, (U.uiflag & USER_CONTINUOUS_MOUSE));
}
else
WM_operator_free(op);
@@ -637,8 +637,8 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
CTX_wm_region_set(C, region);
}
WM_cursor_grab(CTX_wm_window(C), 0, -1);
WM_operator_free(handler->op);
WM_cursor_grab(CTX_wm_window(C), 0);
}
else if(handler->ui_remove) {
ScrArea *area= CTX_wm_area(C);
@@ -835,7 +835,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
/* remove modal handler, operator itself should have been cancelled and freed */
if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
WM_cursor_grab(CTX_wm_window(C), 0);
WM_cursor_grab(CTX_wm_window(C), 0, -1);
BLI_remlink(handlers, handler);
wm_event_free_handler(handler);