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.
This commit is contained in:
parent
4e93918b35
commit
92d747b0c4
|
@ -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);
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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(). */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue