[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [54742] trunk/blender: Toggle-Drag UI Feature
Campbell Barton
ideasman42 at gmail.com
Fri Feb 22 06:56:21 CET 2013
Revision: 54742
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=54742
Author: campbellbarton
Date: 2013-02-22 05:56:20 +0000 (Fri, 22 Feb 2013)
Log Message:
-----------
Toggle-Drag UI Feature
Dragging on toggle buttons can now be used to press multiple buttons at once, especially useful for layer and outliner buttons.
notes:
- automatically enabled for all toggle buttons
(may change this if it becomes a problem).
- only buttons of the same type are pressed
(helps avoid annoyances eg; dragging past layer buttons onto other 3d header buttons and pressing by accident).
- automatic axis locking - dragging will lock to X/Y depending on the initial drag direction,
makes swipe motions work better, especially with the outliner.
implementation details:
- may re-implement as a region handler (currently its a modal operator).
- checking buttons in-between cursor motion events could be more efficient (but currently works ok).
- button execution needs to be improved
(currently executing a button thats not under the mouse needed a workaround for passing uiHandleButtonData),
requires further changes to UI code, will do next.
Modified Paths:
--------------
trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py
trunk/blender/source/blender/editors/include/UI_interface.h
trunk/blender/source/blender/editors/interface/interface.c
trunk/blender/source/blender/editors/interface/interface_handlers.c
trunk/blender/source/blender/editors/interface/interface_intern.h
trunk/blender/source/blender/editors/interface/interface_ops.c
Modified: trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py
===================================================================
--- trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py 2013-02-22 04:09:04 UTC (rev 54741)
+++ trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py 2013-02-22 05:56:20 UTC (rev 54742)
@@ -1060,7 +1060,7 @@
col.label("Show Zero Weights:")
rowsub = col.row()
rowsub.active = (not tool_settings.use_multipaint)
- rowsub.prop(tool_settings, "vertex_group_user", text="Show Group Use", expand=True)
+ rowsub.prop(tool_settings, "vertex_group_user", expand=True)
self.unified_paint_settings(col, context)
Modified: trunk/blender/source/blender/editors/include/UI_interface.h
===================================================================
--- trunk/blender/source/blender/editors/include/UI_interface.h 2013-02-22 04:09:04 UTC (rev 54741)
+++ trunk/blender/source/blender/editors/include/UI_interface.h 2013-02-22 05:56:20 UTC (rev 54742)
@@ -437,6 +437,7 @@
void uiButSetDragImage(uiBut *but, const char *path, int icon, struct ImBuf *ima, float scale);
int UI_but_active_drop_name(struct bContext *C);
+struct uiBut *ui_but_find_mouse_over(struct ARegion *ar, int x, int y);
void uiButSetFlag(uiBut *but, int flag);
void uiButClearFlag(uiBut *but, int flag);
@@ -447,7 +448,9 @@
/* special button case, only draw it when used actively, for outliner etc */
int uiButActiveOnly(const struct bContext *C, uiBlock *block, uiBut *but);
+void uiButExecute(const struct bContext *C, uiBut *but);
+
/* Buttons
*
* Functions to define various types of buttons in a block. Postfixes:
Modified: trunk/blender/source/blender/editors/interface/interface.c
===================================================================
--- trunk/blender/source/blender/editors/interface/interface.c 2013-02-22 04:09:04 UTC (rev 54741)
+++ trunk/blender/source/blender/editors/interface/interface.c 2013-02-22 05:56:20 UTC (rev 54742)
@@ -713,6 +713,12 @@
return 1;
}
+/* simulate button click */
+void uiButExecute(const bContext *C, uiBut *but)
+{
+ ui_button_execute_do((bContext *)C, CTX_wm_region(C), but);
+}
+
/* use to check if we need to disable undo, but don't make any changes
* returns FALSE if undo needs to be disabled. */
static int ui_but_is_rna_undo(uiBut *but)
@@ -1394,6 +1400,18 @@
return 0;
}
+int ui_is_but_bool(uiBut *but)
+{
+ if (ELEM5(but->type, TOG, TOGN, TOGR, ICONTOG, ICONTOGN))
+ return 1;
+
+ if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_BOOLEAN)
+ return 1;
+
+ return 0;
+}
+
+
int ui_is_but_unit(uiBut *but)
{
UnitSettings *unit = but->block->unit;
Modified: trunk/blender/source/blender/editors/interface/interface_handlers.c
===================================================================
--- trunk/blender/source/blender/editors/interface/interface_handlers.c 2013-02-22 04:09:04 UTC (rev 54741)
+++ trunk/blender/source/blender/editors/interface/interface_handlers.c 2013-02-22 05:56:20 UTC (rev 54742)
@@ -85,6 +85,7 @@
/* proto */
static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to);
static void ui_add_link(bContext *C, uiBut *from, uiBut *to);
+static int ui_do_but_EXIT(bContext *C, uiBut *but, struct uiHandleButtonData *data, const wmEvent *event);
/***************** structs and defines ****************/
@@ -761,14 +762,27 @@
WM_gestures_remove(C);
if (ABS(data->dragstartx - event->x) + ABS(data->dragstarty - event->y) > U.dragthreshold) {
- wmDrag *drag;
-
+
button_activate_state(C, but, BUTTON_STATE_EXIT);
data->cancel = TRUE;
- drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but));
- if (but->imb)
- WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect));
+ if (ui_is_but_bool(but)) {
+ const bool is_set = (ui_get_but_val(but) != 0.0);
+ PointerRNA ptr;
+ WM_operator_properties_create(&ptr, "UI_OT_drag_toggle");
+ RNA_boolean_set(&ptr, "state", !is_set);
+ RNA_int_set(&ptr, "last_x", data->dragstartx);
+ RNA_int_set(&ptr, "last_y", data->dragstarty);
+ WM_operator_name_call(C, "UI_OT_drag_toggle", WM_OP_INVOKE_DEFAULT, &ptr);
+ WM_operator_properties_free(&ptr);
+ }
+ else {
+ wmDrag *drag;
+
+ drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but));
+ if (but->imb)
+ WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect));
+ }
return 1;
}
@@ -2472,13 +2486,24 @@
static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS && ui_is_but_bool(but)) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_CONTINUE;
+ }
+
if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
data->togdual = event->ctrl;
data->togonly = !event->shift;
button_activate_state(C, but, BUTTON_STATE_EXIT);
- return WM_UI_HANDLER_BREAK;
+ return WM_UI_HANDLER_CONTINUE;
}
}
+ else if (data->state == BUTTON_STATE_WAIT_DRAG) {
+ /* note: the 'BUTTON_STATE_WAIT_DRAG' part of 'ui_do_but_EXIT' could be refactored into its own function */
+ return ui_do_but_EXIT(C, but, data, event);
+ }
return WM_UI_HANDLER_CONTINUE;
}
@@ -2499,6 +2524,12 @@
return WM_UI_HANDLER_CONTINUE;
}
}
+ if (event->type == LEFTMOUSE && ui_is_but_bool(but)) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_CONTINUE;
+ }
if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
int ret = WM_UI_HANDLER_BREAK;
@@ -3215,6 +3246,12 @@
return WM_UI_HANDLER_BREAK;
}
}
+ if (event->type == LEFTMOUSE && ui_is_but_bool(but)) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_BREAK;
+ }
/* regular open menu */
if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
@@ -5415,7 +5452,7 @@
return 1;
}
-static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
+uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
{
uiBlock *block;
uiBut *but, *butover = NULL;
@@ -5784,8 +5821,10 @@
ED_region_tag_redraw(data->region);
/* clean up button */
- MEM_freeN(but->active);
- but->active = NULL;
+ if (but->active) {
+ MEM_freeN(but->active);
+ but->active = NULL;
+ }
but->flag &= ~(UI_ACTIVE | UI_SELECT);
but->flag |= UI_BUT_LAST_ACTIVE;
if (!onfree)
@@ -6034,6 +6073,20 @@
ui_do_button(C, but->block, but, &event);
}
+void ui_button_execute_do(struct bContext *C, struct ARegion *ar, uiBut *but)
+{
+ /* note: ideally we would not have to change 'but->active' howevwer
+ * some functions we call don't use data (as they should be doing) */
+ void *active_back = but->active;
+ uiHandleButtonData *data = MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData_Fake");
+ but->active = data;
+ data->region = ar;
+ ui_apply_button(C, but->block, but, data, true);
+ /* use onfree event so undo is handled by caller and apply is already done above */
+ button_activate_exit((bContext *)C, data, but, false, true);
+ but->active = active_back;
+}
+
static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type)
{
uiBut *oldbut;
Modified: trunk/blender/source/blender/editors/interface/interface_intern.h
===================================================================
--- trunk/blender/source/blender/editors/interface/interface_intern.h 2013-02-22 04:09:04 UTC (rev 54741)
+++ trunk/blender/source/blender/editors/interface/interface_intern.h 2013-02-22 05:56:20 UTC (rev 54742)
@@ -406,6 +406,7 @@
extern void ui_check_but(uiBut *but);
extern int ui_is_but_float(uiBut *but);
+extern int ui_is_but_bool(uiBut *but);
extern int ui_is_but_unit(uiBut *but);
extern int ui_is_but_rna_valid(uiBut *but);
extern int ui_is_but_utf8(uiBut *but);
@@ -509,6 +510,7 @@
/* interface_handlers.c */
extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but);
+extern void ui_button_execute_do(struct bContext *C, struct ARegion *ar, uiBut *but);
extern void ui_button_active_free(const struct bContext *C, uiBut *but);
extern int ui_button_is_active(struct ARegion *ar);
extern int ui_button_open_menu_direction(uiBut *but);
Modified: trunk/blender/source/blender/editors/interface/interface_ops.c
===================================================================
--- trunk/blender/source/blender/editors/interface/interface_ops.c 2013-02-22 04:09:04 UTC (rev 54741)
+++ trunk/blender/source/blender/editors/interface/interface_ops.c 2013-02-22 05:56:20 UTC (rev 54742)
@@ -1071,6 +1071,228 @@
ot->exec = reloadtranslation_exec;
}
+
+/* -------------------------------------------------------------------- */
+/* Toggle Drag Operator */
+
+typedef struct DragOpInfo {
+ bool xy_lock[2];
+ float but_cent_start[2];
+ eButType but_type_start;
+} DragOpInfo;
+
+typedef struct DragOpPlotData {
+ bContext *C;
+ ARegion *ar;
+ bool is_set;
+ eButType but_type_start;
+ bool do_draw;
+ const uiBut *but_prev;
+} DragOpPlotData;
+
+static const uiBut *ui_but_set_xy(bContext *C, ARegion *ar, const bool is_set, const eButType but_type_start,
+ const int xy[2], const uiBut *but_prev)
+{
+ uiBut *but = ui_but_find_mouse_over(ar, xy[0], xy[1]);
+
+ if (but_prev == but) {
+ return but_prev;
+ }
+
+ if (but && ui_is_but_bool(but) && but->type == but_type_start) {
+ /* is it pressed? */
+ bool is_set_but = (ui_get_but_val(but) != 0.0);
+ BLI_assert(ui_is_but_bool(but) == true);
+ if (is_set_but != is_set) {
+ uiButExecute(C, but);
+ return but;
+ }
+ }
+
+ return but_prev;
+}
+
+static int ui_but_set_cb(int x, int y, void *data_v)
+{
+ DragOpPlotData *data = data_v;
+ int xy[2] = {x, y};
+ data->but_prev = ui_but_set_xy(data->C, data->ar, data->is_set, data->but_type_start, xy, data->but_prev);
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list