From 4375e7ff0b74f96447e27f78a0d9245353d36865 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 5 Aug 2018 12:14:55 +0200 Subject: WM: internal changes to support dragging multiple IDs. To be used by the outliner. --- source/blender/editors/space_node/space_node.c | 4 +- source/blender/editors/space_text/space_text.c | 2 +- source/blender/editors/space_view3d/space_view3d.c | 8 +- source/blender/windowmanager/WM_api.h | 8 +- source/blender/windowmanager/WM_types.h | 9 ++ source/blender/windowmanager/intern/wm_dragdrop.c | 95 ++++++++++++++++------ 6 files changed, 92 insertions(+), 34 deletions(-) diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 2b2e659d151..51ba3a62d1b 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -692,14 +692,14 @@ static bool node_mask_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = drag->poin; + ID *id = WM_drag_ID(drag, 0); RNA_string_set(drop->ptr, "name", id->name + 2); } static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = drag->poin; + ID *id = WM_drag_ID(drag, 0); if (id) { RNA_string_set(drop->ptr, "name", id->name + 2); diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 469e1b84c29..f3c55aa3474 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -499,7 +499,7 @@ static bool text_drop_paste_poll(bContext *UNUSED(C), wmDrag *drag, const wmEven static void text_drop_paste(wmDrag *drag, wmDropBox *drop) { char *text; - ID *id = drag->poin; + ID *id = WM_drag_ID(drag, 0); /* copy drag path to properties */ text = RNA_path_full_ID_py(id); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 68ea59859da..98c5c4e604d 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -632,14 +632,14 @@ static bool view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent * static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = drag->poin; + ID *id = WM_drag_ID(drag, ID_OB); RNA_string_set(drop->ptr, "name", id->name + 2); } static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = drag->poin; + ID *id = WM_drag_ID(drag, ID_GR); drop->opcontext = WM_OP_EXEC_DEFAULT; RNA_string_set(drop->ptr, "name", id->name + 2); @@ -647,14 +647,14 @@ static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop) static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = drag->poin; + ID *id = WM_drag_ID(drag, 0); RNA_string_set(drop->ptr, "name", id->name + 2); } static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = drag->poin; + ID *id = WM_drag_ID(drag, 0); if (id) { RNA_string_set(drop->ptr, "name", id->name + 2); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index d175b11fe5c..b15ce2d11ad 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -484,15 +484,17 @@ void WM_event_drag_image(struct wmDrag *, struct ImBuf *, float scale, int sx void WM_drag_free(struct wmDrag *drag); void WM_drag_free_list(struct ListBase *lb); -struct ID *WM_drag_ID(const struct wmDrag *drag, short idcode); -struct ID *WM_drag_ID_from_event(const struct wmEvent *event, short idcode); - struct wmDropBox *WM_dropbox_add( ListBase *lb, const char *idname, bool (*poll)(struct bContext *, struct wmDrag *, const struct wmEvent *event, const char **), void (*copy)(struct wmDrag *, struct wmDropBox *)); ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid); + /* ID drag and drop */ +void WM_drag_add_ID(struct wmDrag *drag, struct ID *id, struct ID *from_parent); +struct ID *WM_drag_ID(const struct wmDrag *drag, short idcode); +struct ID *WM_drag_ID_from_event(const struct wmEvent *event, short idcode); + /* Set OpenGL viewport and scissor */ void wmViewport(const struct rcti *rect); void wmPartialViewport(rcti *drawrct, const rcti *winrct, const rcti *partialrct); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 809588b1a36..4882741680a 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -111,6 +111,7 @@ struct wmEvent; struct wmWindowManager; struct wmMsgBus; struct wmOperator; +struct ID; struct ImBuf; #include "RNA_types.h" @@ -660,6 +661,12 @@ typedef enum wmDragFlags { /* note: structs need not exported? */ +typedef struct wmDragID { + struct wmDragID *next, *prev; + struct ID *id; + struct ID *from_parent; +} wmDragID; + typedef struct wmDrag { struct wmDrag *next, *prev; @@ -674,6 +681,8 @@ typedef struct wmDrag { char opname[200]; /* if set, draws operator name*/ unsigned int flags; + + ListBase ids; /* List of wmDragIDs, all are guaranteed to have the same ID type. */ } wmDrag; /* dropboxes are like keymaps, part of the screen/area/region definition */ diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index 6b9a7fb5430..0c77ad89292 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -45,6 +45,7 @@ #include "BIF_glutil.h" #include "BKE_context.h" +#include "BKE_idcode.h" #include "GPU_shader.h" @@ -155,10 +156,17 @@ wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, drag->flags = flags; drag->icon = icon; drag->type = type; - if (type == WM_DRAG_PATH) + if (type == WM_DRAG_PATH) { BLI_strncpy(drag->path, poin, FILE_MAX); - else + } + else if (type == WM_DRAG_ID) { + if (poin) { + WM_drag_add_ID(drag, poin, NULL); + } + } + else { drag->poin = poin; + } drag->value = value; return drag; @@ -178,6 +186,7 @@ void WM_drag_free(wmDrag *drag) MEM_freeN(drag->poin); } + BLI_freelistN(&drag->ids); MEM_freeN(drag); } @@ -190,26 +199,6 @@ void WM_drag_free_list(struct ListBase *lb) } -ID *WM_drag_ID(const wmDrag *drag, short idcode) -{ - if (drag->type != WM_DRAG_ID) { - return NULL; - } - - ID *id = drag->poin; - return (idcode == 0 || GS(id->name) == idcode) ? id : NULL; -} - -ID *WM_drag_ID_from_event(const wmEvent *event, short idcode) -{ - if (event->custom != EVT_DATA_DRAGDROP) { - return NULL; - } - - ListBase *lb = event->customdata; - return WM_drag_ID(lb->first, idcode); -} - static const char *dropbox_active(bContext *C, ListBase *handlers, wmDrag *drag, const wmEvent *event) { wmEventHandler *handler = handlers->first; @@ -290,6 +279,57 @@ void wm_drags_check_ops(bContext *C, const wmEvent *event) } } +/* ************** IDs ***************** */ + +void WM_drag_add_ID(wmDrag *drag, ID *id, ID *from_parent) +{ + /* Don't drag the same ID twice. */ + for (wmDragID *drag_id = drag->ids.first; drag_id; drag_id = drag_id->next) { + if (drag_id->id == id) { + if (drag_id->from_parent == NULL) { + drag_id->from_parent = from_parent; + } + return; + } + else if (GS(drag_id->id->name) != GS(id->name)) { + BLI_assert(!"All dragged IDs must have the same type"); + return; + } + } + + /* Add to list. */ + wmDragID *drag_id = MEM_callocN(sizeof(wmDragID), __func__); + drag_id->id = id; + drag_id->from_parent = from_parent; + BLI_addtail(&drag->ids, drag_id); +} + +ID *WM_drag_ID(const wmDrag *drag, short idcode) +{ + if (drag->type != WM_DRAG_ID) { + return NULL; + } + + wmDragID *drag_id = drag->ids.first; + if (!drag_id) { + return NULL; + } + + ID *id = drag_id->id; + return (idcode == 0 || GS(id->name) == idcode) ? id : NULL; + +} + +ID *WM_drag_ID_from_event(const wmEvent *event, short idcode) +{ + if (event->custom != EVT_DATA_DRAGDROP) { + return NULL; + } + + ListBase *lb = event->customdata; + return WM_drag_ID(lb->first, idcode); +} + /* ************** draw ***************** */ static void wm_drop_operator_draw(const char *name, int x, int y) @@ -306,8 +346,15 @@ static const char *wm_drag_name(wmDrag *drag) switch (drag->type) { case WM_DRAG_ID: { - ID *id = drag->poin; - return id->name + 2; + ID *id = WM_drag_ID(drag, 0); + bool single = (BLI_listbase_count_at_most(&drag->ids, 2) == 1); + + if (single) { + return id->name + 2; + } + else { + return BKE_idcode_to_name_plural(GS(id->name)); + } } case WM_DRAG_PATH: case WM_DRAG_NAME: -- cgit v1.2.3