[Bf-blender-cvs] [83c53d1bee2] asset-browser-poselib: Support custom context menu entries for UI-lists, e.g. for pose assets

Julian Eisel noreply at git.blender.org
Thu Apr 1 17:38:58 CEST 2021


Commit: 83c53d1bee2544f52d5b685d94fb89c73c476c19
Author: Julian Eisel
Date:   Thu Apr 1 17:32:49 2021 +0200
Branches: asset-browser-poselib
https://developer.blender.org/rB83c53d1bee2544f52d5b685d94fb89c73c476c19

Support custom context menu entries for UI-lists, e.g. for pose assets

Makes it possible to add custom entries to the context menu of UI List items, by doing the following:
`bpy.types.UI_MT_list_item_context_menu.prepend(some_draw_function)`/`append(...)`.

The given draw function must check if the list is of the correct type. For that
to work I made it possible to get the hovered UI List using `context.ui_list`
and the list-ID via `ui_list.list_id`.

===================================================================

M	release/scripts/addons
M	release/scripts/addons_contrib
M	release/scripts/startup/bl_ui/__init__.py
M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface_context_menu.c
M	source/blender/editors/interface/interface_handlers.c
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_query.c
M	source/blender/editors/interface/interface_template_asset_view.cc
M	source/blender/editors/interface/interface_template_search_menu.c
M	source/blender/editors/interface/interface_templates.c
M	source/blender/editors/screen/screen_context.c
M	source/blender/makesrna/intern/rna_ui.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_uilist_type.c

===================================================================

diff --git a/release/scripts/addons b/release/scripts/addons
index 66e77b34fa1..c294704a0f9 160000
--- a/release/scripts/addons
+++ b/release/scripts/addons
@@ -1 +1 @@
-Subproject commit 66e77b34fa13dcab57ff4552c87a6450a6b73c42
+Subproject commit c294704a0f9430ccd1f4d1f16534d741b2209826
diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib
index f948f658ba3..5523cbaed60 160000
--- a/release/scripts/addons_contrib
+++ b/release/scripts/addons_contrib
@@ -1 +1 @@
-Subproject commit f948f658ba33eb670a65e0bba058d43138abea7e
+Subproject commit 5523cbaed60719960f5f7b2486925145ecbe81e5
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index c282b3f281d..c539b9d8499 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -253,3 +253,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)
\ No newline at end of file
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index cb6b6686cef..99f53a81636 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -550,6 +550,8 @@ bool UI_block_is_empty_ex(const uiBlock *block, const bool skip_title);
 bool UI_block_is_empty(const uiBlock *block);
 bool UI_block_can_add_separator(const uiBlock *block);
 
+struct uiList *UI_list_find_mouse_over(struct ARegion *region, const struct wmEvent *event);
+
 /* interface_region_menu_popup.c */
 /**
  * Popup Menus
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 91c19ff2850..6b35f9cba8a 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -20,6 +20,7 @@
  * Generic context popup menus.
  */
 
+#include <stdio.h>
 #include <string.h>
 
 #include "MEM_guardedalloc.h"
@@ -494,7 +495,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. */
@@ -1234,6 +1235,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 e38a7438214..cf938d3d0e1 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -7668,7 +7668,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;
       }
     }
@@ -9082,11 +9082,6 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
   return retval;
 }
 
-static bool ui_but_is_listrow(const uiBut *but)
-{
-  return but->type == UI_BTYPE_LISTROW;
-}
-
 /**
  * Activate the underlying list-row button, so the row is highlighted.
  * Early exits if \a activate_dragging is true, but the custom drag operator fails to execute.
@@ -9112,8 +9107,7 @@ static int ui_list_activate_hovered_row(bContext *C,
   }
 
   const int *mouse_xy = ISTWEAK(event->type) ? &event->prevclickx : &event->x;
-  uiBut *listrow = ui_but_find_mouse_over_ex(
-      region, mouse_xy[0], mouse_xy[1], false, ui_but_is_listrow);
+  uiBut *listrow = ui_list_row_find_mouse_over(region, mouse_xy[0], mouse_xy[1]);
   if (listrow) {
     wmOperatorType *custom_activate_optype = ui_list->dyn_data->custom_activate_optype;
 
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 80a8260787b..ed0631ce8c8 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -1117,6 +1117,9 @@ bool ui_but_contains_point_px(const uiBut *but, const struct ARegion *region, in
 
 uiBut *ui_list_find_mouse_over(struct ARegion *region,
                                const struct wmEvent *event) ATTR_WARN_UNUSED_RESULT;
+uiBut *ui_list_row_find_mouse_over(const struct ARegion *region,
+                                   int x,
+                                   int y) ATTR_WARN_UNUSED_RESULT;
 
 typedef bool (*uiButFindPoll)(const uiBut *but);
 uiBut *ui_but_find_mouse_over_ex(const struct ARegion *region,
@@ -1168,7 +1171,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_query.c b/source/blender/editors/interface/interface_query.c
index dbff486e0d1..bb3dd6218e8 100644
--- a/source/blender/editors/interface/interface_query.c
+++ b/source/blender/editors/interface/interface_query.c
@@ -265,11 +265,8 @@ bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *region, const wmEv
 }
 
 /* x and y are only used in case event is NULL... */
-uiBut *ui_but_find_mouse_over_ex(const ARegion *region,
-                                 const int x,
-                                 const int y,
-                                 const bool labeledit,
-                                 uiButFindPoll find_poll)
+uiBut *ui_but_find_mouse_over_ex(
+    const ARegion *region, const int x, const int y, const bool labeledit, uiButFindPoll find_poll)
 {
   uiBut *butover = NULL;
 
@@ -376,6 +373,26 @@ uiBut *ui_list_find_mouse_over(ARegion *region, const wmEvent *event)
   return ui_list_find_mouse_over_ex(region, event->x, event->y);
 }
 
+uiList *UI_list_find_mouse_over(ARegion *region, const wmEvent *event)
+{
+  uiBut *list_but = ui_list_find_mouse_over(region, event);
+  if (!list_but) {
+    return NULL;
+  }
+
+  return list_but->custom_data;
+}
+
+static bool ui_but_is_listrow(const uiBut *but)
+{
+  return but->type == UI_BTYPE_LISTROW;
+}
+
+uiBut *ui_list_row_find_mouse_over(const ARegion *region, const int x, const int y)
+{
+  return ui_but_find_mouse_over_ex(region, x, y, false, ui_but_is_listrow);
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/interface/interface_template_asset_view.cc b/source/blender/editors/interface/interface_template_asset_view.cc
index 66947928711..8eff15fe765 100644
--- a/source/blender/editors/interface/interface_template_asset_view.cc
+++ b/source/blender/editors/interface/interface_template_asset_view.cc
@@ -140,6 +140,7 @@ static uiListType *UI_UL_asset_view()
   return list_type;
 }
 
+/* TODO move to a proper place. */
 void ED_uilisttypes_ui()
 {
   WM_uilisttype_add(UI_UL_asset_view());
diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c
index ff42d434f29..8e3b1a307c1 100644
--- a/source/blender/editors/interface/interface_template_search_menu.c
+++ b/source/blender/editors/interface/interface_template_search_menu.c
@@ -1030,7 +1030,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;
@@ -1051,7 +1051,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/interface/interface_templates.c b/sou

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list