diff options
author | Julian Eisel <julian@blender.org> | 2022-01-28 18:42:23 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2022-01-28 18:53:37 +0300 |
commit | 92d747b0c46e2645b7308edd31c778634c68c2c5 (patch) | |
tree | 0516b51e31fbd2c95c57d2d42cde12f6c4d1e7cf /source/blender | |
parent | 4e93918b35facdc1ef8aa84d234c0687418006e2 (diff) |
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.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 2 | ||||
-rw-r--r-- | source/blender/editors/interface/interface.c | 5 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_types.h | 4 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_dragdrop.c | 49 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_event_system.h | 1 |
6 files changed, 63 insertions, 0 deletions
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. */ |