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/include/UI_interface.h5
-rw-r--r--source/blender/editors/interface/interface.c246
-rw-r--r--source/blender/editors/interface/interface_handlers.c127
-rw-r--r--source/blender/editors/interface/interface_intern.h25
-rw-r--r--source/blender/editors/interface/interface_ops.c29
-rw-r--r--source/blender/editors/interface/interface_widgets.c36
-rw-r--r--source/blender/windowmanager/WM_types.h10
7 files changed, 338 insertions, 140 deletions
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index da4097bb544..702d319817f 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1598,6 +1598,11 @@ void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN);
void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, void *arg);
+PointerRNA *UI_but_extra_operator_icon_add(uiBut *but,
+ const char *opname,
+ short opcontext,
+ int icon);
+
/* Autocomplete
*
* Tab complete helper functions, for use in uiButCompleteFunc callbacks.
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 7bfd0200362..27a33a38b15 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1469,6 +1469,187 @@ void ui_but_override_flag(uiBut *but)
}
}
+/** \name Button Extra Operator Icons
+ *
+ * Extra icons are shown on the right hand side of buttons. They can be clicked to invoke custom
+ * operators.
+ * There are some predefined here, which get added to buttons automatically based on button data
+ * (type, flags, state, etc).
+ * \{ */
+
+/**
+ * Predefined types for generic extra operator icons (uiButExtraOpIcon).
+ */
+typedef enum PredefinedExtraOpIconType {
+ PREDEFINED_EXTRA_OP_ICON_NONE = 1,
+ PREDEFINED_EXTRA_OP_ICON_CLEAR,
+ PREDEFINED_EXTRA_OP_ICON_EYEDROPPER,
+} PredefinedExtraOpIconType;
+
+static PointerRNA *ui_but_extra_operator_icon_add_ptr(uiBut *but,
+ wmOperatorType *optype,
+ short opcontext,
+ int icon)
+{
+ uiButExtraOpIcon *extra_op_icon = MEM_mallocN(sizeof(*extra_op_icon), __func__);
+
+ extra_op_icon->icon = (BIFIconID)icon;
+ extra_op_icon->optype_params = MEM_callocN(sizeof(*extra_op_icon->optype_params),
+ "uiButExtraOpIcon.optype_hook");
+ extra_op_icon->optype_params->optype = optype;
+ extra_op_icon->optype_params->opptr = MEM_callocN(sizeof(*extra_op_icon->optype_params->opptr),
+ "uiButExtraOpIcon.optype_hook.opptr");
+ WM_operator_properties_create_ptr(extra_op_icon->optype_params->opptr,
+ extra_op_icon->optype_params->optype);
+ extra_op_icon->optype_params->opcontext = opcontext;
+
+ BLI_addtail(&but->extra_op_icons, extra_op_icon);
+
+ return extra_op_icon->optype_params->opptr;
+}
+
+static void ui_but_extra_operator_icon_free(uiButExtraOpIcon *extra_icon)
+{
+ WM_operator_properties_free(extra_icon->optype_params->opptr);
+ MEM_freeN(extra_icon->optype_params->opptr);
+ MEM_freeN(extra_icon->optype_params);
+ MEM_freeN(extra_icon);
+}
+
+void ui_but_extra_operator_icons_free(uiBut *but)
+{
+
+ for (uiButExtraOpIcon *op_icon = but->extra_op_icons.first, *op_icon_next; op_icon;
+ op_icon = op_icon_next) {
+ op_icon_next = op_icon->next;
+ ui_but_extra_operator_icon_free(op_icon);
+ }
+ BLI_listbase_clear(&but->extra_op_icons);
+}
+
+PointerRNA *UI_but_extra_operator_icon_add(uiBut *but,
+ const char *opname,
+ short opcontext,
+ int icon)
+{
+ wmOperatorType *optype = WM_operatortype_find(opname, false);
+
+ if (optype) {
+ return ui_but_extra_operator_icon_add_ptr(but, optype, opcontext, icon);
+ }
+
+ return NULL;
+}
+
+static bool ui_but_icon_extra_is_visible_text_clear(const uiBut *but)
+{
+ BLI_assert(but->type == UI_BTYPE_TEXT);
+ return ((but->flag & UI_BUT_VALUE_CLEAR) && but->drawstr[0]);
+}
+
+static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but)
+{
+ BLI_assert(ELEM(but->type, UI_BTYPE_SEARCH_MENU));
+ return ((but->editstr == NULL) && (but->drawstr[0] != '\0') && (but->flag & UI_BUT_VALUE_CLEAR));
+}
+
+static bool ui_but_icon_extra_is_visible_search_eyedropper(uiBut *but)
+{
+ StructRNA *type;
+ short idcode;
+
+ BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_VALUE_CLEAR));
+
+ if (but->rnaprop == NULL) {
+ return false;
+ }
+
+ type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
+ idcode = RNA_type_to_ID_code(type);
+
+ return ((but->editstr == NULL) && (idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode)));
+}
+
+static PredefinedExtraOpIconType ui_but_icon_extra_get(uiBut *but)
+{
+ switch (but->type) {
+ case UI_BTYPE_TEXT:
+ if (ui_but_icon_extra_is_visible_text_clear(but)) {
+ return PREDEFINED_EXTRA_OP_ICON_CLEAR;
+ }
+ break;
+ case UI_BTYPE_SEARCH_MENU:
+ if ((but->flag & UI_BUT_VALUE_CLEAR) == 0) {
+ /* pass */
+ }
+ else if (ui_but_icon_extra_is_visible_search_unlink(but)) {
+ return PREDEFINED_EXTRA_OP_ICON_CLEAR;
+ }
+ else if (ui_but_icon_extra_is_visible_search_eyedropper(but)) {
+ return PREDEFINED_EXTRA_OP_ICON_EYEDROPPER;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return PREDEFINED_EXTRA_OP_ICON_NONE;
+}
+
+/**
+ * While some extra operator icons have to be set explicitly upon button creating, this code adds
+ * some generic ones based on button data. Currently these are mutually exclusive, so there's only
+ * ever one predefined extra icon.
+ */
+static void ui_but_predefined_extra_operator_icons_add(uiBut *but)
+{
+ PredefinedExtraOpIconType extra_icon = ui_but_icon_extra_get(but);
+ wmOperatorType *optype = NULL;
+ BIFIconID icon = ICON_NONE;
+
+ switch (extra_icon) {
+ case PREDEFINED_EXTRA_OP_ICON_EYEDROPPER: {
+ static wmOperatorType *id_eyedropper_ot = NULL;
+ if (!id_eyedropper_ot) {
+ id_eyedropper_ot = WM_operatortype_find("UI_OT_eyedropper_id", false);
+ }
+ BLI_assert(id_eyedropper_ot);
+
+ optype = id_eyedropper_ot;
+ icon = ICON_EYEDROPPER;
+
+ break;
+ }
+ case PREDEFINED_EXTRA_OP_ICON_CLEAR: {
+ static wmOperatorType *clear_ot = NULL;
+ if (!clear_ot) {
+ clear_ot = WM_operatortype_find("UI_OT_button_string_clear", false);
+ }
+ BLI_assert(clear_ot);
+
+ optype = clear_ot;
+ icon = ICON_PANEL_CLOSE;
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (optype) {
+ for (uiButExtraOpIcon *op_icon = but->extra_op_icons.first; op_icon; op_icon = op_icon->next) {
+ if ((op_icon->optype_params->optype == optype) && (op_icon->icon == icon)) {
+ /* Don't add the same operator icon twice (happens if button is kept alive while active).
+ */
+ return;
+ }
+ }
+ ui_but_extra_operator_icon_add_ptr(but, optype, WM_OP_INVOKE_DEFAULT, (int)icon);
+ }
+}
+
+/** \} */
+
void UI_block_update_from_old(const bContext *C, uiBlock *block)
{
uiBut *but_old;
@@ -1541,6 +1722,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
if (UI_but_is_decorator(but)) {
ui_but_anim_decorate_update_from_flag(but);
}
+ ui_but_predefined_extra_operator_icons_add(but);
}
/* handle pending stuff */
@@ -2281,69 +2463,6 @@ uiBut *ui_but_drag_multi_edit_get(uiBut *but)
return but_iter;
}
-/** \name Check to show extra icons
- *
- * Extra icons are shown on the right hand side of buttons.
- * This could (should!) definitely become more generic, but for now this is good enough.
- * \{ */
-
-static bool ui_but_icon_extra_is_visible_text_clear(const uiBut *but)
-{
- BLI_assert(but->type == UI_BTYPE_TEXT);
- return ((but->flag & UI_BUT_VALUE_CLEAR) && but->drawstr[0]);
-}
-
-static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but)
-{
- BLI_assert(ELEM(but->type, UI_BTYPE_SEARCH_MENU));
- return ((but->editstr == NULL) && (but->drawstr[0] != '\0') && (but->flag & UI_BUT_VALUE_CLEAR));
-}
-
-static bool ui_but_icon_extra_is_visible_search_eyedropper(uiBut *but)
-{
- StructRNA *type;
- short idcode;
-
- BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_VALUE_CLEAR));
-
- if (but->rnaprop == NULL) {
- return false;
- }
-
- type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
- idcode = RNA_type_to_ID_code(type);
-
- return ((but->editstr == NULL) && (idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode)));
-}
-
-uiButExtraIconType ui_but_icon_extra_get(uiBut *but)
-{
- switch (but->type) {
- case UI_BTYPE_TEXT:
- if (ui_but_icon_extra_is_visible_text_clear(but)) {
- return UI_BUT_ICONEXTRA_CLEAR;
- }
- break;
- case UI_BTYPE_SEARCH_MENU:
- if ((but->flag & UI_BUT_VALUE_CLEAR) == 0) {
- /* pass */
- }
- else if (ui_but_icon_extra_is_visible_search_unlink(but)) {
- return UI_BUT_ICONEXTRA_CLEAR;
- }
- else if (ui_but_icon_extra_is_visible_search_eyedropper(but)) {
- return UI_BUT_ICONEXTRA_EYEDROPPER;
- }
- break;
- default:
- break;
- }
-
- return UI_BUT_ICONEXTRA_NONE;
-}
-
-/** \} */
-
static double ui_get_but_scale_unit(uiBut *but, double value)
{
UnitSettings *unit = but->block->unit;
@@ -3087,6 +3206,7 @@ static void ui_but_free(const bContext *C, uiBut *but)
if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
MEM_freeN(but->dragpoin);
}
+ ui_but_extra_operator_icons_free(but);
BLI_assert(UI_butstore_is_registered(but->block, but) == false);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 9a16cc6d41f..65655c74ee9 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -2673,15 +2673,19 @@ void ui_but_text_password_hide(char password_str[UI_MAX_PASSWORD_STR],
/** \name Button Text Selection/Editing
* \{ */
-static void ui_textedit_string_clear_and_exit(bContext *C, uiBut *but, uiHandleButtonData *data)
+void ui_but_active_string_clear_and_exit(bContext *C, uiBut *but)
{
+ if (!but->active) {
+ return;
+ }
+
/* most likely NULL, but let's check, and give it temp zero string */
- if (!data->str) {
- data->str = MEM_callocN(1, "temp str");
+ if (!but->active->str) {
+ but->active->str = MEM_callocN(1, "temp str");
}
- data->str[0] = 0;
+ but->active->str[0] = 0;
- ui_apply_but_TEX(C, but, data);
+ ui_apply_but_TEX(C, but, but->active);
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
@@ -3768,6 +3772,19 @@ static void ui_numedit_apply(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
ED_region_tag_redraw(data->region);
}
+static void ui_but_extra_operator_icon_apply(bContext *C, uiBut *but, uiButExtraOpIcon *op_icon)
+{
+ WM_operator_name_call_ptr(C,
+ op_icon->optype_params->optype,
+ op_icon->optype_params->opcontext,
+ op_icon->optype_params->opptr);
+
+ /* Force recreation of extra operator icons (pseudo update). */
+ ui_but_extra_operator_icons_free(but);
+
+ WM_event_add_mousemove(C);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -3911,6 +3928,46 @@ static uiBut *ui_but_list_row_text_activate(bContext *C,
/** \name Events for Various Button Types
* \{ */
+static uiButExtraOpIcon *ui_but_extra_operator_icon_mouse_over_get(uiBut *but,
+ uiHandleButtonData *data,
+ const wmEvent *event)
+{
+ float xmax = but->rect.xmax;
+ const float icon_size = BLI_rctf_size_y(&but->rect);
+ int x = event->x, y = event->y;
+
+ ui_window_to_block(data->region, but->block, &x, &y);
+ if (!BLI_rctf_isect_pt(&but->rect, x, y)) {
+ return NULL;
+ }
+
+ /* Inverse order, from right to left. */
+ for (uiButExtraOpIcon *op_icon = but->extra_op_icons.last; op_icon; op_icon = op_icon->prev) {
+ if ((x > (xmax - icon_size)) && x < xmax) {
+ return op_icon;
+ }
+ xmax -= icon_size;
+ }
+
+ return NULL;
+}
+
+static bool ui_do_but_extra_operator_icon(bContext *C,
+ uiBut *but,
+ uiHandleButtonData *data,
+ const wmEvent *event)
+{
+ uiButExtraOpIcon *op_icon = ui_but_extra_operator_icon_mouse_over_get(but, data, event);
+
+ if (op_icon) {
+ ui_but_extra_operator_icon_apply(C, but, op_icon);
+ button_activate_exit(C, but, data, false, false);
+ return true;
+ }
+
+ return false;
+}
+
#ifdef USE_DRAG_TOGGLE
/* Shared by any button that supports drag-toggle. */
static bool ui_do_but_ANY_drag_toggle(
@@ -4098,23 +4155,6 @@ static int ui_do_but_KEYEVT(bContext *C,
return WM_UI_HANDLER_CONTINUE;
}
-static bool ui_but_is_mouse_over_icon_extra(const ARegion *region,
- uiBut *but,
- const int mouse_xy[2])
-{
- int x = mouse_xy[0], y = mouse_xy[1];
- rcti icon_rect;
-
- BLI_assert(ui_but_icon_extra_get(but) != UI_BUT_ICONEXTRA_NONE);
-
- ui_window_to_block(region, but->block, &x, &y);
-
- BLI_rcti_rctf_copy(&icon_rect, &but->rect);
- icon_rect.xmin = icon_rect.xmax - (BLI_rcti_size_y(&icon_rect));
-
- return BLI_rcti_isect_pt(&icon_rect, x, y);
-}
-
static int ui_do_but_TAB(
bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
@@ -4168,17 +4208,11 @@ static int ui_do_but_TEX(
else if (but->dt == UI_EMBOSS_NONE && !event->ctrl) {
/* pass */
}
- else {
- const bool has_icon_extra = ui_but_icon_extra_get(but) == UI_BUT_ICONEXTRA_CLEAR;
-
- if (has_icon_extra && ui_but_is_mouse_over_icon_extra(data->region, but, &event->x)) {
- ui_textedit_string_clear_and_exit(C, but, data);
- }
- else {
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- }
- return WM_UI_HANDLER_BREAK;
+ else if (!ui_but_extra_operator_icon_mouse_over_get(but, data, event)) {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
}
+
+ return WM_UI_HANDLER_BREAK;
}
}
else if (data->state == BUTTON_STATE_TEXT_EDITING) {
@@ -4196,27 +4230,12 @@ static int ui_do_but_TEX(
static int ui_do_but_SEARCH_UNLINK(
bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
- const uiButExtraIconType extra_icon_type = ui_but_icon_extra_get(but);
- const bool has_icon_extra = (extra_icon_type != UI_BUT_ICONEXTRA_NONE);
-
/* unlink icon is on right */
- if ((ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY)) && (has_icon_extra == true) &&
- (ui_but_is_mouse_over_icon_extra(data->region, but, &event->x) == true)) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY)) {
/* doing this on KM_PRESS calls eyedropper after clicking unlink icon */
- if (event->val == KM_RELEASE) {
- /* unlink */
- if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
- ui_textedit_string_clear_and_exit(C, but, data);
- }
- /* eyedropper */
- else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
- WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL);
- }
- else {
- BLI_assert(0);
- }
+ if ((event->val == KM_RELEASE) && ui_do_but_extra_operator_icon(C, but, data, event)) {
+ return WM_UI_HANDLER_BREAK;
}
- return WM_UI_HANDLER_BREAK;
}
return ui_do_but_TEX(C, block, but, data, event);
}
@@ -6976,6 +6995,14 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
if (event->type == EVT_DROP) {
ui_but_drop(C, event, but, data);
}
+
+ if ((data->state == BUTTON_STATE_HIGHLIGHT) &&
+ ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) &&
+ (event->val == KM_RELEASE) &&
+ /* Only returns true if the event was handled. */
+ ui_do_but_extra_operator_icon(C, but, data, event)) {
+ return WM_UI_HANDLER_BREAK;
+ }
}
if (but->flag & UI_BUT_DISABLED) {
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 9705f0fa161..5c73b41b778 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -78,14 +78,6 @@ enum {
/* warn: rest of uiBut->flag in UI_interface.h */
};
-/* some buttons display icons only under special conditions
- * (e.g. 'x' icon in search menu) - used with ui_but_icon_extra_get */
-typedef enum uiButExtraIconType {
- UI_BUT_ICONEXTRA_NONE = 1,
- UI_BUT_ICONEXTRA_CLEAR,
- UI_BUT_ICONEXTRA_EYEDROPPER,
-} uiButExtraIconType;
-
/* uiBut->dragflag */
enum {
UI_BUT_DRAGPOIN_FREE = (1 << 0),
@@ -262,6 +254,8 @@ struct uiBut {
short opcontext;
uchar menu_key; /* 'a'-'z', always lower case */
+ ListBase extra_op_icons; /* uiButExtraOpIcon */
+
/* Draggable data, type is WM_DRAG_... */
char dragtype;
short dragflag;
@@ -293,6 +287,16 @@ typedef struct uiButTab {
struct MenuType *menu;
} uiButTab;
+/**
+ * Additional, superimposed icon for a button, invoking an operator.
+ */
+typedef struct uiButExtraOpIcon {
+ struct uiButExtraOpIcon *next, *prev;
+
+ BIFIconID icon;
+ struct wmOperatorCallParams *optype_params;
+} uiButExtraOpIcon;
+
typedef struct ColorPicker {
struct ColorPicker *next, *prev;
/** Color data, may be HSV or HSL. */
@@ -497,14 +501,17 @@ extern bool ui_but_string_set_eval_num(struct bContext *C,
const char *str,
double *value) ATTR_NONNULL();
extern int ui_but_string_get_max_length(uiBut *but);
+/* Clear & exit the active button's string. */
+extern void ui_but_active_string_clear_and_exit(struct bContext *C, uiBut *but) ATTR_NONNULL();
extern uiBut *ui_but_drag_multi_edit_get(uiBut *but);
void ui_def_but_icon(uiBut *but, const int icon, const int flag);
void ui_def_but_icon_clear(uiBut *but);
-extern uiButExtraIconType ui_but_icon_extra_get(uiBut *but);
extern void ui_but_default_set(struct bContext *C, const bool all, const bool use_afterfunc);
+void ui_but_extra_operator_icons_free(uiBut *but);
+
extern void ui_but_rna_menu_convert_to_panel_type(struct uiBut *but, const char *panel_type);
extern void ui_but_rna_menu_convert_to_menu_type(struct uiBut *but, const char *menu_type);
extern bool ui_but_menu_draw_as_popover(const uiBut *but);
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 68d21e88211..b3c46dda4c3 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -1590,6 +1590,34 @@ static void UI_OT_button_execute(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Text Button Clear Operator
+ * \{ */
+
+static int button_string_clear_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ uiBut *but = UI_context_active_but_get(C);
+
+ if (but) {
+ ui_but_active_string_clear_and_exit(C, but);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void UI_OT_button_string_clear(wmOperatorType *ot)
+{
+ ot->name = "Clear Button String";
+ ot->idname = "UI_OT_button_string_clear";
+ ot->description = "Unsets the text of the active button";
+
+ ot->poll = ED_operator_regionactive;
+ ot->exec = button_string_clear_exec;
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Drop Color Operator
* \{ */
@@ -1714,6 +1742,7 @@ void ED_operatortypes_ui(void)
#endif
WM_operatortype_append(UI_OT_reloadtranslation);
WM_operatortype_append(UI_OT_button_execute);
+ WM_operatortype_append(UI_OT_button_string_clear);
/* external */
WM_operatortype_append(UI_OT_eyedropper_color);
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index d3d95401851..a0bb4de96ea 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -2371,13 +2371,29 @@ static BIFIconID widget_icon_id(uiBut *but)
}
}
+static void widget_draw_extra_icons(const uiWidgetColors *wcol,
+ uiBut *but,
+ rcti *rect,
+ float alpha)
+{
+ /* inverse order, from right to left. */
+ for (uiButExtraOpIcon *op_icon = but->extra_op_icons.last; op_icon; op_icon = op_icon->prev) {
+ rcti temp = *rect;
+
+ temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
+
+ widget_draw_icon(but, op_icon->icon, alpha, &temp, wcol->text);
+
+ rect->xmax -= ICON_SIZE_FROM_BUTRECT(rect);
+ }
+}
+
/* draws text and icons for buttons */
static void widget_draw_text_icon(const uiFontStyle *fstyle,
const uiWidgetColors *wcol,
uiBut *but,
rcti *rect)
{
- const uiButExtraIconType extra_icon_type = ui_but_icon_extra_get(but);
const bool show_menu_icon = ui_but_draw_menu_icon(but);
float alpha = (float)wcol->text[3] / 255.0f;
char password_str[UI_MAX_DRAW_STR];
@@ -2499,23 +2515,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
}
/* extra icons, e.g. 'x' icon to clear text or icon for eyedropper */
- if (extra_icon_type != UI_BUT_ICONEXTRA_NONE) {
- rcti temp = *rect;
-
- temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
-
- if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
- widget_draw_icon(but, ICON_PANEL_CLOSE, alpha, &temp, wcol->text);
- }
- else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
- widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, wcol->text);
- }
- else {
- BLI_assert(0);
- }
-
- rect->xmax -= ICON_SIZE_FROM_BUTRECT(rect);
- }
+ widget_draw_extra_icons(wcol, but, rect, alpha);
/* clip but->drawstr to fit in available space */
if (but->editstr && but->pos >= 0) {
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index b3507c7e57e..5ecd3191bfb 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -775,6 +775,16 @@ typedef struct wmOperatorType {
} wmOperatorType;
+/**
+ * Wrapper to reference a wmOperatorType together with some set properties and othere relevant
+ * information to invoke the operator in a customizable way.
+ */
+typedef struct wmOperatorCallParams {
+ struct wmOperatorType *optype;
+ struct PointerRNA *opptr;
+ short opcontext;
+} wmOperatorCallParams;
+
#ifdef WITH_INPUT_IME
/* *********** Input Method Editor (IME) *********** */
/**