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:
-rw-r--r--source/blender/editors/interface/interface_handlers.c19
-rw-r--r--source/blender/editors/interface/interface_template_search_menu.c3
-rw-r--r--source/blender/makesrna/intern/rna_wm.c7
-rw-r--r--source/blender/windowmanager/WM_api.h6
-rw-r--r--source/blender/windowmanager/WM_types.h11
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c26
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c166
-rw-r--r--source/blender/windowmanager/wm_cursors.h2
8 files changed, 234 insertions, 6 deletions
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 977e9661dd9..77ae16d7cc7 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -508,6 +508,7 @@ typedef struct uiAfterFunc {
bContextStore *context;
char undostr[BKE_UNDO_STR_MAX];
+ char drawstr[UI_MAX_DRAW_STR];
} uiAfterFunc;
static void button_activate_init(bContext *C,
@@ -790,6 +791,10 @@ static void ui_handle_afterfunc_add_operator_ex(wmOperatorType *ot,
if (context_but && context_but->context) {
after->context = CTX_store_copy(context_but->context);
}
+
+ if (context_but) {
+ ui_but_drawstr_without_sep_char(context_but, after->drawstr, sizeof(after->drawstr));
+ }
}
void ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext)
@@ -900,6 +905,8 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
after->context = CTX_store_copy(but->context);
}
+ ui_but_drawstr_without_sep_char(but, after->drawstr, sizeof(after->drawstr));
+
but->optype = NULL;
but->opcontext = 0;
but->opptr = NULL;
@@ -1021,7 +1028,8 @@ static void ui_apply_but_funcs_after(bContext *C)
}
if (after.optype) {
- WM_operator_name_call_ptr(C, after.optype, after.opcontext, (after.opptr) ? &opptr : NULL);
+ WM_operator_name_call_ptr_with_depends_on_cursor(
+ C, after.optype, after.opcontext, (after.opptr) ? &opptr : NULL, after.drawstr);
}
if (after.opptr) {
@@ -4190,10 +4198,11 @@ static void ui_but_extra_operator_icon_apply(bContext *C, uiBut *but, uiButExtra
ui_apply_but(C, but->block, but, but->active, true);
}
button_activate_state(C, but, BUTTON_STATE_EXIT);
- WM_operator_name_call_ptr(C,
- op_icon->optype_params->optype,
- op_icon->optype_params->opcontext,
- op_icon->optype_params->opptr);
+ WM_operator_name_call_ptr_with_depends_on_cursor(C,
+ op_icon->optype_params->optype,
+ op_icon->optype_params->opcontext,
+ op_icon->optype_params->opptr,
+ NULL);
/* Force recreation of extra operator icons (pseudo update). */
ui_but_extra_operator_icons_free(but);
diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c
index 3105891142f..672f1b64943 100644
--- a/source/blender/editors/interface/interface_template_search_menu.c
+++ b/source/blender/editors/interface/interface_template_search_menu.c
@@ -955,7 +955,8 @@ static void menu_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2)
switch (item->type) {
case MENU_SEARCH_TYPE_OP: {
CTX_store_set(C, item->op.context);
- WM_operator_name_call_ptr(C, item->op.type, item->op.opcontext, item->op.opptr);
+ WM_operator_name_call_ptr_with_depends_on_cursor(
+ C, item->op.type, item->op.opcontext, item->op.opptr, item->drawstr);
CTX_store_set(C, NULL);
break;
}
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 21a3c087197..31fdbf528bb 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -468,6 +468,13 @@ const EnumPropertyItem rna_enum_operator_type_flag_items[] = {
"is enabled"},
{OPTYPE_GRAB_CURSOR_X, "GRAB_CURSOR_X", 0, "Grab Pointer X", "Grab, only warping the X axis"},
{OPTYPE_GRAB_CURSOR_Y, "GRAB_CURSOR_Y", 0, "Grab Pointer Y", "Grab, only warping the Y axis"},
+ {OPTYPE_DEPENDS_ON_CURSOR,
+ "DEPENDS_ON_CURSOR",
+ 0,
+ "Depends on Cursor",
+ "The initial cursor location is used, "
+ "when running from a menus or buttons the user is prompted to place the cursor "
+ "before beginning the operation"},
{OPTYPE_PRESET, "PRESET", 0, "Preset", "Display a preset button with the operators settings"},
{OPTYPE_INTERNAL, "INTERNAL", 0, "Internal", "Removes the operator from search results"},
{0, NULL, 0, NULL, NULL},
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 7ecbcad886d..189a231616e 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -472,6 +472,12 @@ int WM_operator_call_py(struct bContext *C,
struct ReportList *reports,
const bool is_undo);
+void WM_operator_name_call_ptr_with_depends_on_cursor(struct bContext *C,
+ wmOperatorType *ot,
+ short opcontext,
+ PointerRNA *properties,
+ const char *drawstr);
+
/* Used for keymap and macro items. */
void WM_operator_properties_alloc(struct PointerRNA **ptr,
struct IDProperty **properties,
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index c1730957432..01b4c0419a8 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -184,6 +184,17 @@ enum {
OPTYPE_LOCK_BYPASS = (1 << 9),
/** Special type of undo which doesn't store itself multiple times. */
OPTYPE_UNDO_GROUPED = (1 << 10),
+
+ /**
+ * Depends on the cursor location, when activated from a menu wait for mouse press.
+ *
+ * In practice these operators often end up being accessed:
+ * - Directly from key bindings.
+ * - As tools in the toolbar.
+ *
+ * Even so, accessing from the menu should behave usefully.
+ */
+ OPTYPE_DEPENDS_ON_CURSOR = (1 << 11),
};
/** For #WM_cursor_grab_enable wrap axis. */
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index 50d3a856cbe..9c020b16234 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -1146,5 +1146,31 @@ void wm_init_cursor_data(void)
BlenderCursor[WM_CURSOR_ZOOM_OUT] = &ZoomOutCursor;
END_CURSOR_BLOCK;
+ /********************** Area Pick Cursor ***********************/
+ BEGIN_CURSOR_BLOCK;
+
+ static char pick_area_bitmap[] = {
+ 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x10,
+ 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0xbf, 0x00, 0x81, 0x00, 0x81,
+ 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x80, 0x00, 0xff,
+ };
+
+ static char pick_area_mask[] = {
+ 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0xff, 0x01, 0xff, 0x01, 0xff,
+ 0x01, 0x38, 0x00, 0xb8, 0x7f, 0xb8, 0xff, 0x80, 0xc1, 0x80, 0xc1,
+ 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xc1, 0x80, 0xff, 0x00, 0xff,
+ };
+
+ static BCursor PickAreaCursor = {
+ pick_area_bitmap,
+ pick_area_mask,
+ 4,
+ 4,
+ false,
+ };
+
+ BlenderCursor[WM_CURSOR_PICK_AREA] = &PickAreaCursor;
+ END_CURSOR_BLOCK;
+
/********************** Put the cursors in the array ***********************/
}
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 83a9a6c6383..238172276e7 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1673,6 +1673,172 @@ int WM_operator_call_py(bContext *C,
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Operator Wait For Input
+ *
+ * Delay executing operators that depend on cursor location.
+ *
+ * See: #OPTYPE_DEPENDS_ON_CURSOR doc-string for more information.
+ * \{ */
+
+typedef struct uiOperatorWaitForInput {
+ ScrArea *area;
+ wmOperatorCallParams optype_params;
+ bContextStore *context;
+} uiOperatorWaitForInput;
+
+static void ui_handler_wait_for_input_remove(bContext *C, void *userdata)
+{
+ uiOperatorWaitForInput *opwait = userdata;
+ if (opwait->optype_params.opptr) {
+ if (opwait->optype_params.opptr->data) {
+ IDP_FreeProperty(opwait->optype_params.opptr->data);
+ }
+ MEM_freeN(opwait->optype_params.opptr);
+ }
+ if (opwait->context) {
+ CTX_store_free(opwait->context);
+ }
+
+ if (opwait->area != NULL) {
+ ED_area_status_text(opwait->area, NULL);
+ }
+ else {
+ ED_workspace_status_text(C, NULL);
+ }
+
+ MEM_freeN(opwait);
+}
+
+static int ui_handler_wait_for_input(bContext *C, const wmEvent *event, void *userdata)
+{
+ uiOperatorWaitForInput *opwait = userdata;
+ enum { CONTINUE = 0, EXECUTE, CANCEL } state = CONTINUE;
+ state = CONTINUE;
+
+ switch (event->type) {
+ case LEFTMOUSE: {
+ if (event->val == KM_PRESS) {
+ state = EXECUTE;
+ }
+ break;
+ }
+ /* Useful if the operator isn't convenient to access while the mouse button is held.
+ * If it takes numeric input for example. */
+ case EVT_SPACEKEY:
+ case EVT_RETKEY: {
+ if (event->val == KM_PRESS) {
+ state = EXECUTE;
+ }
+ break;
+ }
+ case RIGHTMOUSE: {
+ if (event->val == KM_PRESS) {
+ state = CANCEL;
+ }
+ break;
+ }
+ case EVT_ESCKEY: {
+ if (event->val == KM_PRESS) {
+ state = CANCEL;
+ }
+ break;
+ }
+ }
+
+ if (state != CONTINUE) {
+ wmWindow *win = CTX_wm_window(C);
+ WM_cursor_modal_restore(win);
+
+ if (state == EXECUTE) {
+ CTX_store_set(C, opwait->context);
+ WM_operator_name_call_ptr(C,
+ opwait->optype_params.optype,
+ opwait->optype_params.opcontext,
+ opwait->optype_params.opptr);
+ CTX_store_set(C, NULL);
+ }
+
+ WM_event_remove_ui_handler(&win->modalhandlers,
+ ui_handler_wait_for_input,
+ ui_handler_wait_for_input_remove,
+ opwait,
+ false);
+
+ ui_handler_wait_for_input_remove(C, opwait);
+
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
+void WM_operator_name_call_ptr_with_depends_on_cursor(
+ bContext *C, wmOperatorType *ot, short opcontext, PointerRNA *properties, const char *drawstr)
+{
+ int flag = ot->flag;
+
+ LISTBASE_FOREACH (wmOperatorTypeMacro *, macro, &ot->macro) {
+ wmOperatorType *otm = WM_operatortype_find(macro->idname, 0);
+ if (otm != NULL) {
+ flag |= otm->flag;
+ }
+ }
+
+ if ((flag & OPTYPE_DEPENDS_ON_CURSOR) == 0) {
+ WM_operator_name_call_ptr(C, ot, opcontext, properties);
+ return;
+ }
+
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *area = CTX_wm_area(C);
+
+ {
+ char header_text[UI_MAX_DRAW_STR];
+ SNPRINTF(header_text,
+ "%s %s",
+ IFACE_("Input pending "),
+ (drawstr && drawstr[0]) ? drawstr : CTX_IFACE_(ot->translation_context, ot->name));
+ if (area != NULL) {
+ ED_area_status_text(area, header_text);
+ }
+ else {
+ ED_workspace_status_text(C, header_text);
+ }
+ }
+
+ WM_cursor_modal_set(win, WM_CURSOR_PICK_AREA);
+
+ uiOperatorWaitForInput *opwait = MEM_callocN(sizeof(*opwait), __func__);
+ opwait->optype_params.optype = ot;
+ opwait->optype_params.opcontext = opcontext;
+ opwait->optype_params.opptr = properties;
+
+ opwait->area = area;
+
+ if (properties) {
+ opwait->optype_params.opptr = MEM_mallocN(sizeof(*opwait->optype_params.opptr), __func__);
+ *opwait->optype_params.opptr = *properties;
+ if (properties->data != NULL) {
+ opwait->optype_params.opptr->data = IDP_CopyProperty(properties->data);
+ }
+ }
+
+ bContextStore *store = CTX_store_get(C);
+ if (store) {
+ opwait->context = CTX_store_copy(store);
+ }
+
+ WM_event_add_ui_handler(C,
+ &win->modalhandlers,
+ ui_handler_wait_for_input,
+ ui_handler_wait_for_input_remove,
+ opwait,
+ WM_HANDLER_BLOCKING);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Handler Types
*
* General API for different handler types.
diff --git a/source/blender/windowmanager/wm_cursors.h b/source/blender/windowmanager/wm_cursors.h
index 2842538ebf1..d1694454490 100644
--- a/source/blender/windowmanager/wm_cursors.h
+++ b/source/blender/windowmanager/wm_cursors.h
@@ -74,6 +74,8 @@ typedef enum WMCursorType {
WM_CURSOR_NONE,
WM_CURSOR_MUTE,
+ WM_CURSOR_PICK_AREA,
+
/* --- ALWAYS LAST ----- */
WM_CURSOR_NUM,
} WMCursorType;