Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Eisel <eiseljulian@gmail.com>2019-10-04 16:11:19 +0300
committerJulian Eisel <eiseljulian@gmail.com>2019-10-04 17:46:32 +0300
commitbe2cd4bb5325fa7950a412fdd14448d49b342b57 (patch)
tree17db2242628db893831dd4594601579edcd011b5 /source/blender/windowmanager/intern/wm_operators.c
parent0bcada85b362fcc1874a1bf13ece157870c0fea7 (diff)
WM: Utilities for select operators to work with click-dragging items
Based on work by Bastien and Brecht in the Node Editor, this adds more generalized support for selecting items so that click+drag actions on items (nodes, makers, dopesheet keys, etc.) works as wanted. Note that this only adds the barebones to support this in other editors, it's not used yet (will be done in followup commits). The behavior is supposed to work as follows: * Clicking an unselected item immediately selects it, and deselects other items (doesn't wait for release events). * Click+drag on an unselected item immediately selects it, deselects others and drags it in one go (don't require selecting it first!). * Click+drag on a selected item won't change the selection state (and won't send an undo push) and start dragging all selected items as soon as the drag event is recognized. * Clicking on a selected item will still deselect others, but that will only happen on mouse release, when we know the intention is not to drag the item. Included in: https://developer.blender.org/D5979 Reviewed by: Brecht van Lommel, William Reynish
Diffstat (limited to 'source/blender/windowmanager/intern/wm_operators.c')
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 97771d40b2c..292e27c3cbf 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -700,6 +700,82 @@ void WM_operator_properties_free(PointerRNA *ptr)
/** \name Default Operator Callbacks
* \{ */
+int WM_generic_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ PropertyRNA *wait_to_deselect_prop = RNA_struct_find_property(op->ptr,
+ "wait_to_deselect_others");
+ const short init_event_type = (short)POINTER_AS_INT(op->customdata);
+ int ret_value = 0;
+
+ /* get settings from RNA properties for operator */
+ int mval[2];
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
+
+ if (init_event_type == 0) {
+ if (event->val == KM_PRESS) {
+ RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, true);
+
+ ret_value = op->type->exec(C, op);
+ OPERATOR_RETVAL_CHECK(ret_value);
+
+ op->customdata = POINTER_FROM_INT((int)event->type);
+ if (ret_value & OPERATOR_RUNNING_MODAL) {
+ WM_event_add_modal_handler(C, op);
+ }
+ return ret_value | OPERATOR_PASS_THROUGH;
+ }
+ else {
+ /* If we are in init phase, and cannot validate init of modal operations,
+ * just fall back to basic exec.
+ */
+ RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, false);
+
+ ret_value = op->type->exec(C, op);
+ OPERATOR_RETVAL_CHECK(ret_value);
+
+ return ret_value | OPERATOR_PASS_THROUGH;
+ }
+ }
+ else if (event->type == init_event_type && event->val == KM_RELEASE) {
+ RNA_property_boolean_set(op->ptr, wait_to_deselect_prop, false);
+
+ ret_value = op->type->exec(C, op);
+ OPERATOR_RETVAL_CHECK(ret_value);
+
+ return ret_value | OPERATOR_PASS_THROUGH;
+ }
+ else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ const int drag_delta[2] = {
+ mval[0] - event->mval[0],
+ mval[1] - event->mval[1],
+ };
+ /* If user moves mouse more than defined threshold, we consider select operator as
+ * finished. Otherwise, it is still running until we get an 'release' event. In any
+ * case, we pass through event, but select op is not finished yet. */
+ if (WM_event_drag_test_with_delta(event, drag_delta)) {
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ }
+ else {
+ /* Important not to return anything other than PASS_THROUGH here,
+ * otherwise it prevents underlying tweak detection code to work properly. */
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+}
+
+int WM_generic_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ RNA_int_set(op->ptr, "mouse_x", event->mval[0]);
+ RNA_int_set(op->ptr, "mouse_y", event->mval[1]);
+
+ op->customdata = POINTER_FROM_INT(0);
+
+ return op->type->modal(C, op, event);
+}
+
void WM_operator_view3d_unit_defaults(struct bContext *C, struct wmOperator *op)
{
if (op->flag & OP_IS_INVOKE) {