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--release/scripts/startup/bl_ui/__init__.py24
-rw-r--r--source/blender/editors/interface/interface_context_menu.c16
-rw-r--r--source/blender/editors/interface/interface_handlers.c2
-rw-r--r--source/blender/editors/interface/interface_intern.h2
-rw-r--r--source/blender/editors/interface/interface_template_search_menu.c4
-rw-r--r--source/blender/editors/screen/screen_context.c11
-rw-r--r--source/blender/makesrna/intern/rna_ui.c31
-rw-r--r--source/blender/windowmanager/WM_api.h1
-rw-r--r--source/blender/windowmanager/intern/wm_uilist_type.c14
9 files changed, 98 insertions, 7 deletions
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index ef705f8fe37..25484e905c3 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -117,13 +117,15 @@ def register():
for cls in mod.classes:
register_class(cls)
- # space_userprefs.py
from bpy.props import (
EnumProperty,
StringProperty,
)
- from bpy.types import WindowManager
+ from bpy.types import (
+ WindowManager,
+ )
+ # space_userprefs.py
def addon_filter_items(_self, _context):
import addon_utils
@@ -234,3 +236,21 @@ class UI_UL_list(bpy.types.UIList):
bpy.utils.register_class(UI_UL_list)
+
+
+class UI_MT_list_item_context_menu(bpy.types.Menu):
+ """
+ UI List item context menu definition. Scripts can append/prepend this to
+ add own operators to the context menu. They must check context though, so
+ their items only draw in a valid context and for the correct UI list.
+ """
+
+ bl_label = "List Item"
+ bl_idname = "UI_MT_list_item_context_menu"
+
+ def draw(self, context):
+ # Dummy function. This type is just for scripts to append their own
+ # context menu items.
+ pass
+
+bpy.utils.register_class(UI_MT_list_item_context_menu)
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 2a7611eabb1..3049e2bd7b8 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -494,7 +494,7 @@ static void ui_but_menu_add_path_operators(uiLayout *layout, PointerRNA *ptr, Pr
RNA_string_set(&props_ptr, "filepath", dir);
}
-bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
+bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *event)
{
/* ui_but_is_interactive() may let some buttons through that should not get a context menu - it
* doesn't make sense for them. */
@@ -1226,6 +1226,20 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
}
}
+ /* UI List item context menu. Scripts can add items to it, by default there's nothing shown. */
+ ARegion *region = CTX_wm_region(C);
+ const bool is_inside_listbox = ui_list_find_mouse_over(region, event) != NULL;
+ const bool is_inside_listrow = is_inside_listbox ?
+ ui_list_row_find_mouse_over(region, event->x, event->y) !=
+ NULL :
+ false;
+ if (is_inside_listrow) {
+ MenuType *mt = WM_menutype_find("UI_MT_list_item_context_menu", true);
+ if (mt) {
+ UI_menutype_draw(C, mt, uiLayoutColumn(layout, false));
+ }
+ }
+
MenuType *mt = WM_menutype_find("WM_MT_button_context", true);
if (mt) {
UI_menutype_draw(C, mt, uiLayoutColumn(layout, false));
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 2f03539873f..cd975e97613 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -7909,7 +7909,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
if ((event->type == RIGHTMOUSE) && !IS_EVENT_MOD(event, shift, ctrl, alt, oskey) &&
(event->val == KM_PRESS)) {
/* RMB has two options now */
- if (ui_popup_context_menu_for_button(C, but)) {
+ if (ui_popup_context_menu_for_button(C, but, event)) {
return WM_UI_HANDLER_BREAK;
}
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index ab76de8bdba..efc94b89046 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -1191,7 +1191,7 @@ struct ARegion *ui_screen_region_find_mouse_over(struct bScreen *screen,
const struct wmEvent *event);
/* interface_context_menu.c */
-bool ui_popup_context_menu_for_button(struct bContext *C, uiBut *but);
+bool ui_popup_context_menu_for_button(struct bContext *C, uiBut *but, const struct wmEvent *event);
void ui_popup_context_menu_for_panel(struct bContext *C,
struct ARegion *region,
struct Panel *panel);
diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c
index f01dca7712c..3105891142f 100644
--- a/source/blender/editors/interface/interface_template_search_menu.c
+++ b/source/blender/editors/interface/interface_template_search_menu.c
@@ -1037,7 +1037,7 @@ static void menu_search_update_fn(const bContext *UNUSED(C),
static bool ui_search_menu_create_context_menu(struct bContext *C,
void *arg,
void *active,
- const struct wmEvent *UNUSED(event))
+ const struct wmEvent *event)
{
struct MenuSearch_Data *data = arg;
struct MenuSearch_Item *item = active;
@@ -1058,7 +1058,7 @@ static bool ui_search_menu_create_context_menu(struct bContext *C,
CTX_wm_region_set(C, item->wm_context->region);
}
- if (ui_popup_context_menu_for_button(C, but)) {
+ if (ui_popup_context_menu_for_button(C, but, event)) {
has_menu = true;
}
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index ece6ba986f3..3ce2f326dca 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -112,6 +112,7 @@ const char *screen_context_dir[] = {
"selected_editable_fcurves",
"active_editable_fcurve",
"selected_editable_keyframes",
+ "ui_list",
"asset_library",
NULL,
};
@@ -1034,6 +1035,15 @@ static eContextResult screen_ctx_asset_library(const bContext *C, bContextDataRe
return CTX_RESULT_OK;
}
+static eContextResult screen_ctx_ui_list(const bContext *C, bContextDataResult *result)
+{
+ wmWindow *win = CTX_wm_window(C);
+ ARegion *region = CTX_wm_region(C);
+ uiList *list = UI_list_find_mouse_over(region, win->eventstate);
+ CTX_data_pointer_set(result, NULL, &RNA_UIList, list);
+ return CTX_RESULT_OK;
+}
+
/* Registry of context callback functions. */
typedef eContextResult (*context_callback)(const bContext *C, bContextDataResult *result);
@@ -1109,6 +1119,7 @@ static void ensure_ed_screen_context_functions(void)
register_context_function("active_editable_fcurve", screen_ctx_active_editable_fcurve);
register_context_function("selected_editable_keyframes", screen_ctx_selected_editable_keyframes);
register_context_function("asset_library", screen_ctx_asset_library);
+ register_context_function("ui_list", screen_ctx_ui_list);
}
/* Entry point for the screen context. */
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index 849bbca16f4..2a076554d03 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -458,6 +458,27 @@ static IDProperty **rna_UIList_idprops(PointerRNA *ptr)
return &ui_list->properties;
}
+static void rna_UIList_list_id_get(PointerRNA *ptr, char *value)
+{
+ uiList *ui_list = (uiList *)ptr->data;
+ if (!ui_list->type) {
+ value[0] = '\0';
+ return;
+ }
+
+ strcpy(value, WM_uilisttype_list_id_get(ui_list->type, ui_list));
+}
+
+static int rna_UIList_list_id_length(PointerRNA *ptr)
+{
+ uiList *ui_list = (uiList *)ptr->data;
+ if (!ui_list->type) {
+ return 0;
+ }
+
+ return strlen(WM_uilisttype_list_id_get(ui_list->type, ui_list));
+}
+
static void uilist_draw_item(uiList *ui_list,
bContext *C,
uiLayout *layout,
@@ -1535,6 +1556,16 @@ static void rna_def_uilist(BlenderRNA *brna)
"script, then bl_idname = \"OBJECT_UL_vgroups\")");
/* Data */
+ /* Note that this is the "non-full" list-ID as obtained through #WM_uilisttype_list_id_get(),
+ * which differs from the (internal) `uiList.list_id`. */
+ prop = RNA_def_property(srna, "list_id", PROP_STRING, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_string_funcs(prop, "rna_UIList_list_id_get", "rna_UIList_list_id_length", NULL);
+ RNA_def_property_ui_text(prop,
+ "List Name",
+ "Identifier of the list, if any was passed to the \"list_id\" "
+ "parameter of \"template_list()\"");
+
prop = RNA_def_property(srna, "layout_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_uilist_layout_type_items);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 601db427381..c529fef73ef 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -624,6 +624,7 @@ void WM_uilisttype_free(void);
void WM_uilisttype_to_full_list_id(const struct uiListType *ult,
const char *list_id,
char *r_ui_list_id);
+const char *WM_uilisttype_list_id_get(const struct uiListType *ult, struct uiList *list);
/* wm_menu_type.c */
void WM_menutype_init(void);
diff --git a/source/blender/windowmanager/intern/wm_uilist_type.c b/source/blender/windowmanager/intern/wm_uilist_type.c
index 434131903fc..6d298ee63f1 100644
--- a/source/blender/windowmanager/intern/wm_uilist_type.c
+++ b/source/blender/windowmanager/intern/wm_uilist_type.c
@@ -21,6 +21,7 @@
*/
#include <stdio.h>
+#include <string.h>
#include "BLI_sys_types.h"
@@ -109,3 +110,16 @@ void WM_uilisttype_to_full_list_id(const uiListType *ult,
/* We tag the list id with the list type... */
BLI_snprintf(r_full_list_id, UI_MAX_NAME_STR, "%s_%s", ult->idname, list_id ? list_id : "");
}
+
+/**
+ * Get the "non-full" list-ID, see #WM_uilisttype_to_full_list_id() for details.
+ *
+ * \note Assumes `uiList.list_id` was set using #WM_uilisttype_to_full_list_id()!
+ */
+const char *WM_uilisttype_list_id_get(const uiListType *ult, uiList *list)
+{
+ /* Some sanity check for the assumed behavior of #WM_uilisttype_to_full_list_id(). */
+ BLI_assert((list->list_id + strlen(ult->idname))[0] == '_');
+ /* +1 to skip the '_' */
+ return list->list_id + strlen(ult->idname) + 1;
+}