[Bf-blender-cvs] [92d747b0c46] master: Drag & drop: Support using context of hovered button when dropping

Julian Eisel noreply at git.blender.org
Fri Jan 28 16:53:50 CET 2022


Commit: 92d747b0c46e2645b7308edd31c778634c68c2c5
Author: Julian Eisel
Date:   Fri Jan 28 16:42:23 2022 +0100
Branches: master
https://developer.blender.org/rB92d747b0c46e2645b7308edd31c778634c68c2c5

Drag & drop: Support using context of hovered button when dropping

Buttons can hold context and it's very useful to use this as a way to
let buttons provide context for drop operators.
For example, with this D13549 can make the material slot list set the
material-slot pointer for each row, and the drop operator can just query
that.

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

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface.c
M	source/blender/windowmanager/WM_types.h
M	source/blender/windowmanager/intern/wm_dragdrop.c
M	source/blender/windowmanager/intern/wm_event_system.c
M	source/blender/windowmanager/wm_event_system.h

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

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 3796fa51499..ae4c2ff16fd 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1370,6 +1370,8 @@ uiBut *uiDefIconTextButO_ptr(uiBlock *block,
 /* for passing inputs to ButO buttons */
 struct PointerRNA *UI_but_operator_ptr_get(uiBut *but);
 
+struct bContextStore *UI_but_context_get(const uiBut *but);
+
 void UI_but_unit_type_set(uiBut *but, int unit_type);
 int UI_but_unit_type_get(const uiBut *but);
 
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 636281ba373..2292bf759b7 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -5928,6 +5928,11 @@ PointerRNA *UI_but_operator_ptr_get(uiBut *but)
   return but->opptr;
 }
 
+bContextStore *UI_but_context_get(const uiBut *but)
+{
+  return but->context;
+}
+
 void UI_but_unit_type_set(uiBut *but, const int unit_type)
 {
   but->unit_type = (uchar)(RNA_SUBTYPE_UNIT_VALUE(unit_type));
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index d1f790ce3e2..929b39715b9 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -1048,6 +1048,10 @@ typedef struct wmDragActiveDropState {
    * it as needed. */
   struct ARegion *region_from;
 
+  /** If `active_dropbox` is set, additional context provided by the active (i.e. hovered) button.
+   * Activated before context sensitive operations (polling, drawing, dropping). */
+  struct bContextStore *ui_context;
+
   /** Text to show when a dropbox poll succeeds (so the dropbox itself is available) but the
    * operator poll fails. Typically the message the operator set with
    * CTX_wm_operator_poll_msg_set(). */
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 96cb66b44ea..3bc77db45ca 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -226,6 +226,30 @@ void wm_drags_exit(wmWindowManager *wm, wmWindow *win)
   }
 }
 
+static bContextStore *wm_drop_ui_context_create(const bContext *C)
+{
+  uiBut *active_but = UI_region_active_but_get(CTX_wm_region(C));
+  if (!active_but) {
+    return NULL;
+  }
+
+  bContextStore *but_context = UI_but_context_get(active_but);
+  if (!but_context) {
+    return NULL;
+  }
+
+  return CTX_store_copy(but_context);
+}
+
+static void wm_drop_ui_context_free(bContextStore **context_store)
+{
+  if (!*context_store) {
+    return;
+  }
+  CTX_store_free(*context_store);
+  *context_store = NULL;
+}
+
 void WM_event_drag_image(wmDrag *drag, ImBuf *imb, float scale, int sx, int sy)
 {
   drag->imb = imb;
@@ -259,6 +283,7 @@ void WM_drag_free(wmDrag *drag)
   if (drag->flags & WM_DRAG_FREE_DATA) {
     WM_drag_data_free(drag->type, drag->poin);
   }
+  wm_drop_ui_context_free(&drag->drop_state.ui_context);
   if (drag->drop_state.free_disabled_info) {
     MEM_SAFE_FREE(drag->drop_state.disabled_info);
   }
@@ -317,6 +342,10 @@ static wmDropBox *dropbox_active(bContext *C,
           }
 
           const wmOperatorCallContext opcontext = wm_drop_operator_context_get(drop);
+          if (drag->drop_state.ui_context) {
+            CTX_store_set(C, drag->drop_state.ui_context);
+          }
+
           if (WM_operator_poll_context(C, drop->ot, opcontext)) {
             return drop;
           }
@@ -367,6 +396,10 @@ static void wm_drop_update_active(bContext *C, wmDrag *drag, const wmEvent *even
     return;
   }
 
+  /* Update UI context, before polling so polls can query this context. */
+  wm_drop_ui_context_free(&drag->drop_state.ui_context);
+  drag->drop_state.ui_context = wm_drop_ui_context_create(C);
+
   wmDropBox *drop_prev = drag->drop_state.active_dropbox;
   wmDropBox *drop = wm_dropbox_active(C, drag, event);
   if (drop != drop_prev) {
@@ -381,11 +414,20 @@ static void wm_drop_update_active(bContext *C, wmDrag *drag, const wmEvent *even
     drag->drop_state.area_from = drop ? CTX_wm_area(C) : NULL;
     drag->drop_state.region_from = drop ? CTX_wm_region(C) : NULL;
   }
+
+  if (!drag->drop_state.active_dropbox) {
+    wm_drop_ui_context_free(&drag->drop_state.ui_context);
+  }
 }
 
 void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop)
 {
   const wmOperatorCallContext opcontext = wm_drop_operator_context_get(drop);
+
+  if (drag->drop_state.ui_context) {
+    CTX_store_set(C, drag->drop_state.ui_context);
+  }
+
   /* Optionally copy drag information to operator properties. Don't call it if the
    * operator fails anyway, it might do more than just set properties (e.g.
    * typically import an asset). */
@@ -396,6 +438,11 @@ void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop)
   wm_drags_exit(CTX_wm_manager(C), CTX_wm_window(C));
 }
 
+void wm_drop_end(bContext *C, wmDrag *UNUSED(drag), wmDropBox *UNUSED(drop))
+{
+  CTX_store_set(C, NULL);
+}
+
 void wm_drags_check_ops(bContext *C, const wmEvent *event)
 {
   wmWindowManager *wm = CTX_wm_manager(C);
@@ -897,6 +944,7 @@ void wm_drags_draw(bContext *C, wmWindow *win)
     if (drag->drop_state.active_dropbox) {
       CTX_wm_area_set(C, drag->drop_state.area_from);
       CTX_wm_region_set(C, drag->drop_state.region_from);
+      CTX_store_set(C, drag->drop_state.ui_context);
 
       /* Drawing should be allowed to assume the context from handling and polling (that's why we
        * restore it above). */
@@ -915,4 +963,5 @@ void wm_drags_draw(bContext *C, wmWindow *win)
   GPU_blend(GPU_BLEND_NONE);
   CTX_wm_area_set(C, NULL);
   CTX_wm_region_set(C, NULL);
+  CTX_store_set(C, NULL);
 }
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 9d2c97e151f..6cded3dfdb5 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -3076,6 +3076,8 @@ static int wm_handlers_do_intern(bContext *C, wmWindow *win, wmEvent *event, Lis
                   event->customdata = NULL;
                   event->custom = 0;
 
+                  wm_drop_end(C, drag, drop);
+
                   /* XXX fileread case. */
                   if (CTX_wm_window(C) == NULL) {
                     return action;
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index 925be8ab183..252ff228bc1 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -199,6 +199,7 @@ void wm_dropbox_free(void);
  */
 void wm_drags_exit(wmWindowManager *wm, wmWindow *win);
 void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop);
+void wm_drop_end(bContext *C, wmDrag *drag, wmDropBox *drop);
 /**
  * Called in inner handler loop, region context.
  */



More information about the Bf-blender-cvs mailing list