[Bf-blender-cvs] [272e0770a03] asset-browser: Proper implementation of "Make Asset" for button context menus

Julian Eisel noreply at git.blender.org
Wed Nov 25 17:21:30 CET 2020


Commit: 272e0770a032805b5675dd317882fd7f81cd76e7
Author: Julian Eisel
Date:   Wed Nov 25 16:58:20 2020 +0100
Branches: asset-browser
https://developer.blender.org/rB272e0770a032805b5675dd317882fd7f81cd76e7

Proper implementation of "Make Asset" for button context menus

Buttons or other UI elements can now set a "focused_id" context pointer. The
asset operators (and in future, general data-block operators) can use this
then. Further the UI code automatically sets it when a button represents a
data-block pointer. That way, data-block search menus or data-block selectors
also show "Make Asset" in the context menu.

This also works for material slots now, the material slot you right click will
properly set the "focused_id" context pointer, and "Make Asset" makes that
material an asset.

Had to add support for using custom context pointers to context menus and
UILists.

Addresses T82664.

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

M	release/scripts/startup/bl_ui/properties_material.py
M	source/blender/blenkernel/BKE_context.h
M	source/blender/blenkernel/intern/context.c
M	source/blender/editors/asset/CMakeLists.txt
M	source/blender/editors/asset/asset_edit.c
M	source/blender/editors/asset/asset_ops.c
M	source/blender/editors/include/ED_asset.h
M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface.c
M	source/blender/editors/interface/interface_context_menu.c
M	source/blender/editors/interface/interface_layout.c
M	source/blender/editors/interface/interface_templates.c

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

diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index 6aaec9940e8..cd6bebfea94 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -42,6 +42,9 @@ class MATERIAL_UL_matslots(UIList):
         # ob = data
         slot = item
         ma = slot.material
+
+        layout.context_pointer_set("focused_id", ma)
+
         if self.layout_type in {'DEFAULT', 'COMPACT'}:
             if ma:
                 layout.prop(ma, "name", text="", emboss=False, icon_value=icon)
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index af9a95e1753..94392dd78da 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -143,8 +143,9 @@ bContext *CTX_copy(const bContext *C);
 
 /* Stored Context */
 
-bContextStore *CTX_store_add(ListBase *contexts, const char *name, PointerRNA *ptr);
+bContextStore *CTX_store_add(ListBase *contexts, const char *name, const PointerRNA *ptr);
 bContextStore *CTX_store_add_all(ListBase *contexts, bContextStore *context);
+bContextStore *CTX_store_get(bContext *C);
 void CTX_store_set(bContext *C, bContextStore *store);
 bContextStore *CTX_store_copy(bContextStore *store);
 void CTX_store_free(bContextStore *store);
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 2e4d3d62925..65accc66084 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -123,7 +123,7 @@ void CTX_free(bContext *C)
 
 /* store */
 
-bContextStore *CTX_store_add(ListBase *contexts, const char *name, PointerRNA *ptr)
+bContextStore *CTX_store_add(ListBase *contexts, const char *name, const PointerRNA *ptr)
 {
   /* ensure we have a context to put the entry in, if it was already used
    * we have to copy the context to ensure */
@@ -178,6 +178,11 @@ bContextStore *CTX_store_add_all(ListBase *contexts, bContextStore *context)
   return ctx;
 }
 
+bContextStore *CTX_store_get(bContext *C)
+{
+  return C->wm.store;
+}
+
 void CTX_store_set(bContext *C, bContextStore *store)
 {
   C->wm.store = store;
diff --git a/source/blender/editors/asset/CMakeLists.txt b/source/blender/editors/asset/CMakeLists.txt
index 8ba15208afc..63a1761b264 100644
--- a/source/blender/editors/asset/CMakeLists.txt
+++ b/source/blender/editors/asset/CMakeLists.txt
@@ -22,6 +22,7 @@ set(INC
     ../../makesdna
     ../../makesrna
     ../../windowmanager
+    ../../../../intern/guardedalloc
 )
 
 set(INC_SYS
diff --git a/source/blender/editors/asset/asset_edit.c b/source/blender/editors/asset/asset_edit.c
index 583fc66ef40..c52e8bc7062 100644
--- a/source/blender/editors/asset/asset_edit.c
+++ b/source/blender/editors/asset/asset_edit.c
@@ -27,6 +27,8 @@
 
 #include "UI_interface_icons.h"
 
+#include "RNA_access.h"
+
 #include "ED_asset.h"
 
 bool ED_asset_make_for_id(const bContext *C, ID *id)
@@ -49,3 +51,9 @@ bool ED_asset_make_for_id(const bContext *C, ID *id)
 
   return true;
 }
+
+bool ED_asset_can_make_single_from_context(const bContext *C)
+{
+  /* Context needs a "focused_id" pointer to be set for #ASSET_OT_make() to use. */
+  return CTX_data_pointer_get_type_silent(C, "focused_id", &RNA_ID).data != NULL;
+}
diff --git a/source/blender/editors/asset/asset_ops.c b/source/blender/editors/asset/asset_ops.c
index 9d14fa72f49..fcd27f3a65a 100644
--- a/source/blender/editors/asset/asset_ops.c
+++ b/source/blender/editors/asset/asset_ops.c
@@ -29,27 +29,54 @@
 
 #include "ED_asset.h"
 
+#include "MEM_guardedalloc.h"
+
 #include "RNA_access.h"
 #include "RNA_define.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
 
+/**
+ * Return the IDs to operate on as list of #CollectionPointerLink links. Needs freeing.
+ */
+static ListBase asset_make_get_ids_from_context(const bContext *C)
+{
+  ListBase list = {0};
+
+  PointerRNA idptr = CTX_data_pointer_get_type(C, "focused_id", &RNA_ID);
+
+  if (idptr.data) {
+    CollectionPointerLink *ctx_link = MEM_callocN(sizeof(*ctx_link), __func__);
+    ctx_link->ptr = idptr;
+    BLI_addtail(&list, ctx_link);
+  }
+  else {
+    CTX_data_selected_ids(C, &list);
+  }
+
+  return list;
+}
+
 static bool asset_make_poll(bContext *C)
 {
+  ListBase ids = asset_make_get_ids_from_context(C);
+
   int tot_selected = 0;
   bool can_make_asset = false;
 
   /* Note that this isn't entirely cheap. Iterates over entire Outliner tree and allocates a link
    * for each selected item. The button only shows in the context menu though, so acceptable. */
-  CTX_DATA_BEGIN (C, ID *, id, selected_ids) {
+  LISTBASE_FOREACH (CollectionPointerLink *, ctx_id, &ids) {
+    ID *id = ctx_id->ptr.data;
+
     tot_selected++;
     if (!id->asset_data) {
       can_make_asset = true;
       break;
     }
   }
-  CTX_DATA_END;
+  BLI_freelistN(&ids);
 
   if (!can_make_asset) {
     if (tot_selected > 0) {
@@ -66,10 +93,14 @@ static bool asset_make_poll(bContext *C)
 
 static int asset_make_exec(bContext *C, wmOperator *op)
 {
+  ListBase ids = asset_make_get_ids_from_context(C);
+
   ID *last_id = NULL;
   int tot_created = 0;
 
-  CTX_DATA_BEGIN (C, ID *, id, selected_ids) {
+  LISTBASE_FOREACH (CollectionPointerLink *, ctx_id, &ids) {
+    ID *id = ctx_id->ptr.data;
+    BLI_assert(RNA_struct_is_ID(ctx_id->ptr.type));
     if (id->asset_data) {
       continue;
     }
@@ -78,7 +109,7 @@ static int asset_make_exec(bContext *C, wmOperator *op)
     last_id = id;
     tot_created++;
   }
-  CTX_DATA_END;
+  BLI_freelistN(&ids);
 
   /* User feedback. */
   if (tot_created < 1) {
diff --git a/source/blender/editors/include/ED_asset.h b/source/blender/editors/include/ED_asset.h
index 7b9f5087da8..672fd80a219 100644
--- a/source/blender/editors/include/ED_asset.h
+++ b/source/blender/editors/include/ED_asset.h
@@ -27,6 +27,8 @@ extern "C" {
 
 bool ED_asset_make_for_id(const struct bContext *C, struct ID *id);
 
+bool ED_asset_can_make_single_from_context(const struct bContext *C);
+
 void ED_operatortypes_asset(void);
 
 #ifdef __cplusplus
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index f11f3546f8d..77db90ef11d 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1885,6 +1885,7 @@ uiBlock *uiLayoutGetBlock(uiLayout *layout);
 
 void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv);
 void uiLayoutSetContextPointer(uiLayout *layout, const char *name, struct PointerRNA *ptr);
+struct bContextStore *uiLayoutGetContextStore(uiLayout *layout);
 void uiLayoutContextCopy(uiLayout *layout, struct bContextStore *context);
 struct wmOperatorType *UI_but_operatortype_get_from_enum_menu(struct uiBut *but,
                                                               PropertyRNA **r_prop);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index c8d5049edec..02224e6f029 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -4552,6 +4552,15 @@ static uiBut *ui_def_but_rna(uiBlock *block,
     UI_but_disable(but, info);
   }
 
+  if (proptype == PROP_POINTER) {
+    /* If the button shows an ID, automatically set it as focused in context so operators can
+     * access it.*/
+    const PointerRNA pptr = RNA_property_pointer_get(ptr, prop);
+    if (pptr.data && RNA_struct_is_ID(pptr.type)) {
+      but->context = CTX_store_add(&block->contexts, "focused_id", &pptr);
+    }
+  }
+
   if (but->flag & UI_BUT_UNDO && (ui_but_is_rna_undo(but) == false)) {
     but->flag &= ~UI_BUT_UNDO;
   }
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 82b5d0a174a..e8fb2c4fd8e 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -38,6 +38,7 @@
 #include "BKE_idprop.h"
 #include "BKE_screen.h"
 
+#include "ED_asset.h"
 #include "ED_keyframing.h"
 #include "ED_screen.h"
 
@@ -515,6 +516,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
 
   uiPopupMenu *pup;
   uiLayout *layout;
+  bContextStore *previous_ctx = CTX_store_get(C);
 
   {
     uiStringInfo label = {BUT_GET_LABEL, NULL};
@@ -527,6 +529,11 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
     if (label.strinfo) {
       MEM_freeN(label.strinfo);
     }
+
+    if (but->context) {
+      uiLayoutContextCopy(layout, but->context);
+      CTX_store_set(C, uiLayoutGetContextStore(layout));
+    }
     uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
   }
 
@@ -957,11 +964,12 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
       ui_but_menu_add_path_operators(layout, ptr, prop);
       uiItemS(layout);
     }
+  }
 
-    if (RNA_struct_is_ID(but->rnapoin.type)) {
-      uiItemO(layout, NULL, ICON_NONE, "ASSET_OT_make");
-      uiItemS(layout);
-    }
+  /* If the button reprents an id, it can set the "focused_id" context pointer. */
+  if (ED_asset_can_make_single_from_context(C)) {
+    uiItemO(layout, NULL, ICON_NONE, "ASSET_OT_make");
+    uiItemS(layout);
   }
 
   /* Pointer properties and string properties with
@@ -1227,6 +1235,10 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
     UI_menutype_draw(C, mt, uiLayoutColumn(layout, false));
   }
 
+  if (but->context) {
+    CTX_store_set(C, previous_ctx);
+  }
+
   return UI_popup_menu_end_or_cancel(C, pup);
 }
 
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index d61e80e6505..8eb8f461a1f 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -5663,6 +5663,11 @@ void uiLayoutSetContextPointer(uiLayout *layout, const char *name, PointerRNA *p
   layout->context = CTX_store_add(&block->contexts, name, ptr);
 }
 
+bContextStore *uiLayoutGetContextStore(uiLayout *layout)
+{
+  return layout->context;
+}
+
 void uiLayoutContex

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list