Blender V4.3
wm_dragdrop.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2010 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <cstring>
12
14
15#include "DNA_asset_types.h"
16#include "DNA_screen_types.h"
17#include "DNA_space_types.h"
19
20#include "MEM_guardedalloc.h"
21
22#include "BLT_translation.hh"
23
24#include "BLI_bitmap.h"
25#include "BLI_blenlib.h"
26#include "BLI_math_color.h"
27
28#include "BIF_glutil.hh"
29
30#include "BKE_context.hh"
31#include "BKE_global.hh"
32#include "BKE_idprop.hh"
33#include "BKE_idtype.hh"
34#include "BKE_lib_id.hh"
35#include "BKE_main.hh"
36#include "BKE_screen.hh"
37
38#include "GHOST_C-api.h"
39
40#include "BLO_readfile.hh"
41
42#include "ED_asset.hh"
43#include "ED_fileselect.hh"
44#include "ED_screen.hh"
45
46#include "GPU_shader.hh"
47#include "GPU_state.hh"
48#include "GPU_viewport.hh"
49
50#include "IMB_imbuf_types.hh"
51
52#include "UI_interface.hh"
53#include "UI_interface_icons.hh"
54#include "UI_resources.hh"
55
56#include "RNA_access.hh"
57
58#include "WM_api.hh"
59#include "WM_types.hh"
60#include "wm_event_system.hh"
61#include "wm_window.hh"
62
63#include <fmt/format.h>
64/* ****************************************************** */
65
66static ListBase dropboxes = {nullptr, nullptr};
67
68static void wm_drag_free_asset_data(wmDragAsset **asset_data);
69static void wm_drag_free_path_data(wmDragPath **path_data);
70
71static void wm_drop_item_free_data(wmDropBox *drop);
72static void wm_drop_item_clear_runtime(wmDropBox *drop);
73
76
77/* Drop box maps are stored global for now. */
78/* These are part of blender's UI/space specs, and not like keymaps. */
79/* When editors become configurable, they can add their own dropbox definitions. */
80
88
89ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid)
90{
92 if (dm->spaceid == spaceid && dm->regionid == regionid) {
93 if (STREQLEN(idname, dm->idname, KMAP_MAX_NAME)) {
94 return &dm->dropboxes;
95 }
96 }
97 }
98
99 wmDropBoxMap *dm = MEM_cnew<wmDropBoxMap>(__func__);
100 STRNCPY_UTF8(dm->idname, idname);
101 dm->spaceid = spaceid;
102 dm->regionid = regionid;
104
105 return &dm->dropboxes;
106}
107
109 const char *idname,
110 bool (*poll)(bContext *C, wmDrag *drag, const wmEvent *event),
111 void (*copy)(bContext *C, wmDrag *drag, wmDropBox *drop),
112 void (*cancel)(Main *bmain, wmDrag *drag, wmDropBox *drop),
113 WMDropboxTooltipFunc tooltip)
114{
115 wmOperatorType *ot = WM_operatortype_find(idname, true);
116 if (ot == nullptr) {
117 printf("Error: dropbox with unknown operator: %s\n", idname);
118 return nullptr;
119 }
120
121 wmDropBox *drop = MEM_cnew<wmDropBox>(__func__);
122 drop->poll = poll;
123 drop->copy = copy;
124 drop->cancel = cancel;
125 drop->tooltip = tooltip;
126 drop->ot = ot;
127 STRNCPY(drop->opname, idname);
128
129 WM_operator_properties_alloc(&(drop->ptr), &(drop->properties), idname);
131
132 /* Signal for no context, see #STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID. */
133 drop->ptr->owner_id = nullptr;
134
135 BLI_addtail(lb, drop);
136
137 return drop;
138}
139
141{
142 /* NOTE(@ideasman42): this closely follows #wm_keymap_item_properties_update_ot.
143 * `keep_properties` is implied because drop boxes aren't dynamically added & removed.
144 * It's possible in the future drop-boxes can be (un)registered by scripts.
145 * In this case we might want to remove drop-boxes that point to missing operators. */
147 if (ot == nullptr) {
148 /* Allow for the operator to be added back and re-validated, keep it's properties. */
150 drop->ot = nullptr;
151 return;
152 }
153
154 if (drop->ptr == nullptr) {
155 WM_operator_properties_alloc(&(drop->ptr), &(drop->properties), drop->opname);
157 }
158 else {
159 if (ot->srna != drop->ptr->type) {
161 if (drop->properties) {
162 drop->ptr->data = drop->properties;
163 }
165 }
166 }
167
168 if (drop->ptr) {
169 drop->ptr->owner_id = nullptr;
170 }
171 drop->ot = ot;
172}
173
175{
177 LISTBASE_FOREACH (wmDropBox *, drop, &dm->dropboxes) {
179 }
180 }
181}
182
184{
185 if (drop->ptr) {
187 MEM_delete(drop->ptr);
188 drop->ptr = nullptr;
189 drop->properties = nullptr;
190 }
191 else if (drop->properties) {
193 drop->properties = nullptr;
194 }
195}
196
198{
199 IDProperty *properties = drop->properties;
200 drop->properties = nullptr;
201 if (drop->ptr) {
202 drop->ptr->data = nullptr;
203 }
205 drop->properties = properties;
206}
207
209{
210
212 LISTBASE_FOREACH (wmDropBox *, drop, &dm->dropboxes) {
214 }
215 BLI_freelistN(&dm->dropboxes);
216 }
217
219}
220
221/* *********************************** */
222
223static void wm_dropbox_invoke(bContext *C, wmDrag *drag)
224{
226
227 /* Create a bitmap flag matrix of all currently visible region and area types.
228 * Everything that isn't visible in the current window should not prefetch any data. */
229 bool area_region_tag[SPACE_TYPE_NUM][RGN_TYPE_NUM] = {{false}};
230
231 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
233 ED_screen_areas_iter (win, screen, area) {
234 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
235 if (region->visible) {
236 BLI_assert(area->spacetype < SPACE_TYPE_NUM);
237 BLI_assert(region->regiontype < RGN_TYPE_NUM);
238 area_region_tag[area->spacetype][region->regiontype] = true;
239 }
240 }
241 }
242 }
243
245 if (!area_region_tag[dm->spaceid][dm->regionid]) {
246 continue;
247 }
248 LISTBASE_FOREACH (wmDropBox *, drop, &dm->dropboxes) {
249 if (drag->drop_state.ui_context) {
250 CTX_store_set(C, drag->drop_state.ui_context.get());
251 }
252
253 if (drop->on_drag_start) {
254 drop->on_drag_start(C, drag);
255 }
256 CTX_store_set(C, nullptr);
257 }
258 }
259}
260
261wmDrag *WM_drag_data_create(bContext *C, int icon, eWM_DragDataType type, void *poin, uint flags)
262{
263 wmDrag *drag = MEM_new<wmDrag>(__func__);
264
265 /* Keep track of future multi-touch drag too, add a mouse-pointer id or so. */
266 /* If multiple drags are added, they're drawn as list. */
267
268 drag->flags = static_cast<eWM_DragFlags>(flags);
269 drag->icon = icon;
270 drag->type = type;
271 switch (type) {
272 case WM_DRAG_PATH:
273 drag->poin = poin;
274 drag->flags |= WM_DRAG_FREE_DATA;
275 break;
276 case WM_DRAG_ID:
277 if (poin) {
278 WM_drag_add_local_ID(drag, static_cast<ID *>(poin), nullptr);
279 }
280 break;
282 case WM_DRAG_ASSET:
284 /* Move ownership of poin to wmDrag. */
285 drag->poin = poin;
286 drag->flags |= WM_DRAG_FREE_DATA;
287 break;
288 /* The asset-list case is special: We get multiple assets from context and attach them to the
289 * drag item. */
290 case WM_DRAG_ASSET_LIST: {
291 blender::Vector<PointerRNA> asset_links = CTX_data_collection_get(C, "selected_assets");
292 for (const PointerRNA &ptr : asset_links) {
293 const AssetRepresentationHandle *asset = static_cast<const AssetRepresentationHandle *>(
294 ptr.data);
295 WM_drag_add_asset_list_item(drag, asset);
296 }
297 break;
298 }
299 default:
300 drag->poin = poin;
301 break;
302 }
303
304 return drag;
305}
306
308{
310
311 BLI_addtail(&wm->drags, drag);
312 wm_dropbox_invoke(C, drag);
313}
314
315void WM_event_start_drag(bContext *C, int icon, eWM_DragDataType type, void *poin, uint flags)
316{
317 wmDrag *drag = WM_drag_data_create(C, icon, type, poin, flags);
319}
320
322{
323 /* Turn off modal cursor for all windows. */
324 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
326 }
327
328 /* Active area should always redraw, even if cancelled. */
329 int event_xy_target[2];
330 wmWindow *target_win = WM_window_find_under_cursor(win, win->eventstate->xy, event_xy_target);
331 if (target_win) {
332 const bScreen *screen = WM_window_get_active_screen(target_win);
333 ED_region_tag_redraw_no_rebuild(screen->active_region);
334
335 /* Ensure the correct area cursor is restored. */
336 target_win->tag_cursor_refresh = true;
337 WM_event_add_mousemove(target_win);
338 }
339}
340
341static std::unique_ptr<bContextStore> wm_drop_ui_context_create(const bContext *C)
342{
344 if (!active_but) {
345 return nullptr;
346 }
347
348 const bContextStore *but_context = UI_but_context_get(active_but);
349 if (!but_context) {
350 return nullptr;
351 }
352
353 return std::make_unique<bContextStore>(*but_context);
354}
355
356void WM_event_drag_image(wmDrag *drag, const ImBuf *imb, float scale)
357{
358 drag->imb = imb;
359 drag->imbuf_scale = scale;
360}
361
362void WM_drag_data_free(eWM_DragDataType dragtype, void *poin)
363{
364 /* Don't require all the callers to have a nullptr-check, just allow passing nullptr. */
365 if (!poin) {
366 return;
367 }
368
369 /* Not too nice, could become a callback. */
370 switch (dragtype) {
371 case WM_DRAG_ASSET: {
372 wmDragAsset *asset_data = static_cast<wmDragAsset *>(poin);
373 wm_drag_free_asset_data(&asset_data);
374 break;
375 }
376 case WM_DRAG_PATH: {
377 wmDragPath *path_data = static_cast<wmDragPath *>(poin);
378 wm_drag_free_path_data(&path_data);
379 break;
380 }
381 case WM_DRAG_STRING: {
382 std::string *str = static_cast<std::string *>(poin);
383 MEM_delete(str);
384 break;
385 }
386 default:
387 MEM_freeN(poin);
388 break;
389 }
390}
391
393{
396 }
397 if (drag->flags & WM_DRAG_FREE_DATA) {
398 WM_drag_data_free(drag->type, drag->poin);
399 }
400 drag->drop_state.ui_context.reset();
401 if (drag->drop_state.free_disabled_info) {
403 }
404 BLI_freelistN(&drag->ids);
406 if (asset_item->is_external) {
407 wm_drag_free_asset_data(&asset_item->asset_data.external_info);
408 }
409 BLI_freelinkN(&drag->asset_items, asset_item);
410 }
411 MEM_delete(drag);
412}
413
415{
416 while (wmDrag *drag = static_cast<wmDrag *>(BLI_pophead(lb))) {
417 WM_drag_free(drag);
418 }
419}
420
421static std::string dropbox_tooltip(bContext *C, wmDrag *drag, const int xy[2], wmDropBox *drop)
422{
423 if (drop->tooltip) {
424 return drop->tooltip(C, drag, xy, drop);
425 }
426 if (drop->ot) {
427 return WM_operatortype_name(drop->ot, drop->ptr);
428 }
429 return {};
430}
431
433 ListBase *handlers,
434 wmDrag *drag,
435 const wmEvent *event)
436{
437 if (drag->drop_state.free_disabled_info) {
439 }
440 drag->drop_state.disabled_info = nullptr;
441
442 LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) {
443 if (handler_base->type == WM_HANDLER_TYPE_DROPBOX) {
444 wmEventHandler_Dropbox *handler = (wmEventHandler_Dropbox *)handler_base;
445 if (handler->dropboxes) {
446 LISTBASE_FOREACH (wmDropBox *, drop, handler->dropboxes) {
447 if (drag->drop_state.ui_context) {
448 CTX_store_set(C, drag->drop_state.ui_context.get());
449 }
450
451 if (!drop->poll(C, drag, event)) {
452 /* If the drop's poll fails, don't set the disabled-info. This would be too aggressive.
453 * Instead show it only if the drop box could be used in principle, but the operator
454 * can't be executed. */
455 continue;
456 }
457
459 if (drop->ot && WM_operator_poll_context(C, drop->ot, opcontext)) {
460 /* Get dropbox tooltip now, #wm_drag_draw_tooltip can use a different draw context. */
461 drag->drop_state.tooltip = dropbox_tooltip(C, drag, event->xy, drop);
462 CTX_store_set(C, nullptr);
463 return drop;
464 }
465
466 /* Attempt to set the disabled hint when the poll fails. Will always be the last hint set
467 * when there are multiple failing polls (could allow multiple disabled-hints too). */
468 bool free_disabled_info = false;
469 const char *disabled_hint = CTX_wm_operator_poll_msg_get(C, &free_disabled_info);
470 if (disabled_hint) {
471 drag->drop_state.disabled_info = disabled_hint;
472 drag->drop_state.free_disabled_info = free_disabled_info;
473 }
474 }
475 }
476 }
477 }
478 CTX_store_set(C, nullptr);
479 return nullptr;
480}
481
482/* Return active operator tooltip/name when mouse is in box. */
483static wmDropBox *wm_dropbox_active(bContext *C, wmDrag *drag, const wmEvent *event)
484{
485 wmWindow *win = CTX_wm_window(C);
487 ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->xy);
488 wmDropBox *drop = nullptr;
489
490 if (area) {
491 ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_ANY, event->xy);
492 if (region) {
493 drop = dropbox_active(C, &region->handlers, drag, event);
494 }
495
496 if (!drop) {
497 drop = dropbox_active(C, &area->handlers, drag, event);
498 }
499 }
500 if (!drop) {
501 drop = dropbox_active(C, &win->handlers, drag, event);
502 }
503 return drop;
504}
505
509static void wm_drop_update_active(bContext *C, wmDrag *drag, const wmEvent *event)
510{
511 wmWindow *win = CTX_wm_window(C);
512 const blender::int2 win_size = WM_window_native_pixel_size(win);
513
514 /* For multi-window drags, we only do this if mouse inside. */
515 if (event->xy[0] < 0 || event->xy[1] < 0 || event->xy[0] > win_size[0] ||
516 event->xy[1] > win_size[1])
517 {
518 return;
519 }
520
521 /* Update UI context, before polling so polls can query this context. */
522 drag->drop_state.ui_context.reset();
524 drag->drop_state.tooltip = "";
525
526 wmDropBox *drop_prev = drag->drop_state.active_dropbox;
527 wmDropBox *drop = wm_dropbox_active(C, drag, event);
528 if (drop != drop_prev) {
529 if (drop_prev && drop_prev->on_exit) {
530 drop_prev->on_exit(drop_prev, drag);
531 BLI_assert(drop_prev->draw_data == nullptr);
532 }
533 if (drop && drop->on_enter) {
534 drop->on_enter(drop, drag);
535 }
536 drag->drop_state.active_dropbox = drop;
537 drag->drop_state.area_from = drop ? CTX_wm_area(C) : nullptr;
538 drag->drop_state.region_from = drop ? CTX_wm_region(C) : nullptr;
539 }
540
541 if (!drag->drop_state.active_dropbox) {
542 drag->drop_state.ui_context.reset();
543 }
544}
545
547{
549
550 if (drag->drop_state.ui_context) {
551 CTX_store_set(C, drag->drop_state.ui_context.get());
552 }
553
554 /* Optionally copy drag information to operator properties. Don't call it if the
555 * operator fails anyway, it might do more than just set properties (e.g.
556 * typically import an asset). */
557 if (drop->copy && WM_operator_poll_context(C, drop->ot, opcontext)) {
558 drop->copy(C, drag, drop);
559 }
560
562}
563
564void wm_drop_end(bContext *C, wmDrag * /*drag*/, wmDropBox * /*drop*/)
565{
566 CTX_store_set(C, nullptr);
567}
568
569void wm_drags_check_ops(bContext *C, const wmEvent *event)
570{
572
573 bool any_active = false;
574 LISTBASE_FOREACH (wmDrag *, drag, &wm->drags) {
575 wm_drop_update_active(C, drag, event);
576
577 if (drag->drop_state.active_dropbox) {
578 any_active = true;
579 }
580 }
581
582 /* Change the cursor to display that dropping isn't possible here. But only if there is something
583 * being dragged actually. Cursor will be restored in #wm_drags_exit(). */
584 if (!BLI_listbase_is_empty(&wm->drags)) {
586 }
587}
588
593
594/* ************** IDs ***************** */
595
596void WM_drag_add_local_ID(wmDrag *drag, ID *id, ID *from_parent)
597{
598 /* Don't drag the same ID twice. */
599 LISTBASE_FOREACH (wmDragID *, drag_id, &drag->ids) {
600 if (drag_id->id == id) {
601 if (drag_id->from_parent == nullptr) {
602 drag_id->from_parent = from_parent;
603 }
604 return;
605 }
606 if (GS(drag_id->id->name) != GS(id->name)) {
607 BLI_assert_msg(0, "All dragged IDs must have the same type");
608 return;
609 }
610 }
611
612 /* Add to list. */
613 wmDragID *drag_id = MEM_cnew<wmDragID>(__func__);
614 drag_id->id = id;
615 drag_id->from_parent = from_parent;
616 BLI_addtail(&drag->ids, drag_id);
617}
618
619ID *WM_drag_get_local_ID(const wmDrag *drag, short idcode)
620{
621 if (drag->type != WM_DRAG_ID) {
622 return nullptr;
623 }
624
625 wmDragID *drag_id = static_cast<wmDragID *>(drag->ids.first);
626 if (!drag_id) {
627 return nullptr;
628 }
629
630 ID *id = drag_id->id;
631 return (idcode == 0 || GS(id->name) == idcode) ? id : nullptr;
632}
633
634ID *WM_drag_get_local_ID_from_event(const wmEvent *event, short idcode)
635{
636 if (event->custom != EVT_DATA_DRAGDROP) {
637 return nullptr;
638 }
639
640 ListBase *lb = static_cast<ListBase *>(event->customdata);
641 return WM_drag_get_local_ID(static_cast<const wmDrag *>(lb->first), idcode);
642}
643
644bool WM_drag_is_ID_type(const wmDrag *drag, int idcode)
645{
646 return WM_drag_get_local_ID(drag, idcode) || WM_drag_get_asset_data(drag, idcode);
647}
648
650 int import_method)
651{
652 wmDragAsset *asset_drag = MEM_new<wmDragAsset>(__func__);
653
654 asset_drag->asset = asset;
655 asset_drag->import_method = import_method;
656
657 return asset_drag;
658}
659
660static void wm_drag_free_asset_data(wmDragAsset **asset_data)
661{
662 if (*asset_data) {
663 MEM_delete(*asset_data);
664 *asset_data = nullptr;
665 }
666}
667
669{
670 if (drag->type != WM_DRAG_ASSET) {
671 return nullptr;
672 }
673
674 wmDragAsset *asset_drag = static_cast<wmDragAsset *>(drag->poin);
675 ID_Type asset_idcode = asset_drag->asset->get_id_type();
676 return ELEM(idcode, 0, asset_idcode) ? asset_drag : nullptr;
677}
678
680{
681 wmDragAsset *drag_asset = WM_drag_get_asset_data(drag, idcode);
682 if (drag_asset) {
683 return &drag_asset->asset->get_metadata();
684 }
685
686 ID *local_id = WM_drag_get_local_ID(drag, idcode);
687 if (local_id) {
688 return local_id->asset_data;
689 }
690
691 return nullptr;
692}
693
694ID *WM_drag_asset_id_import(const bContext *C, wmDragAsset *asset_drag, const int flag_extra)
695{
696 /* Only support passing in limited flags. */
697 BLI_assert(flag_extra == (flag_extra & FILE_AUTOSELECT));
698 eFileSel_Params_Flag flag = static_cast<eFileSel_Params_Flag>(flag_extra) |
700
701 const char *name = asset_drag->asset->get_name().c_str();
702 const std::string blend_path = asset_drag->asset->full_library_path();
703 const ID_Type idtype = asset_drag->asset->get_id_type();
704 const bool use_relative_path = asset_drag->asset->get_use_relative_path();
705
706 /* FIXME: Link/Append should happens in the operator called at the end of drop process, not from
707 * here. */
708
709 Main *bmain = CTX_data_main(C);
710 Scene *scene = CTX_data_scene(C);
711 ViewLayer *view_layer = CTX_data_view_layer(C);
712 View3D *view3d = CTX_wm_view3d(C);
713
714 switch (eAssetImportMethod(asset_drag->import_method)) {
716 return WM_file_link_datablock(bmain,
717 scene,
718 view_layer,
719 view3d,
720 blend_path.c_str(),
721 idtype,
722 name,
723 flag | (use_relative_path ? FILE_RELPATH : 0));
725 return WM_file_append_datablock(bmain,
726 scene,
727 view_layer,
728 view3d,
729 blend_path.c_str(),
730 idtype,
731 name,
736 G_MAIN,
737 scene,
738 view_layer,
739 view3d,
740 blend_path.c_str(),
741 idtype,
742 name,
744 BLO_LIBLINK_APPEND_LOCAL_ID_REUSE | (use_relative_path ? FILE_RELPATH : 0));
745 }
746
748 return nullptr;
749}
750
752{
753 if (drag->type != WM_DRAG_ASSET) {
754 return false;
755 }
756
757 const wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0);
758 return asset_drag->import_method == ASSET_IMPORT_LINK;
759}
760
762{
763 if (!ELEM(drag->type, WM_DRAG_ASSET, WM_DRAG_ID)) {
764 return nullptr;
765 }
766
767 if (drag->type == WM_DRAG_ID) {
768 return WM_drag_get_local_ID(drag, idcode);
769 }
770
771 wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, idcode);
772 if (!asset_drag) {
773 return nullptr;
774 }
775
776 /* Link/append the asset. */
777 return WM_drag_asset_id_import(C, asset_drag, 0);
778}
779
781{
782 if (drag->type != WM_DRAG_ASSET) {
783 return;
784 }
785
786 wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0);
787 if (!asset_drag) {
788 return;
789 }
790
791 ID_Type asset_id_type = asset_drag->asset->get_id_type();
792 /* Try to find the imported ID. For this to work either a "session_uid" or "name" property must
793 * have been defined (see #WM_operator_properties_id_lookup()). */
795 bmain, drop->ptr, asset_id_type);
796 if (id != nullptr) {
797 /* Do not delete the dragged ID if it has any user, otherwise if it is a 're-used' ID it will
798 * cause #95636. Note that we need first to add the user that we want to remove in
799 * #BKE_id_free_us. */
800 id_us_plus(id);
801 BKE_id_free_us(bmain, id);
802 }
803}
804
806{
807 if (drag->type != WM_DRAG_ASSET_CATALOG) {
808 return nullptr;
809 }
810
811 return static_cast<wmDragAssetCatalog *>(drag->poin);
812}
813
816{
818
819 /* No guarantee that the same asset isn't added twice. */
820
821 /* Add to list. */
822 wmDragAssetListItem *drag_asset = MEM_cnew<wmDragAssetListItem>(__func__);
823 ID *local_id = asset->local_id();
824 if (local_id) {
825 drag_asset->is_external = false;
826 drag_asset->asset_data.local_id = local_id;
827 }
828 else {
829 drag_asset->is_external = true;
831 }
832 BLI_addtail(&drag->asset_items, drag_asset);
833}
834
836{
837 if (drag->type != WM_DRAG_ASSET_LIST) {
838 return nullptr;
839 }
840
841 return &drag->asset_items;
842}
843
845{
846 BLI_assert(!paths.is_empty());
847 wmDragPath *path_data = MEM_new<wmDragPath>("wmDragPath");
848
849 for (const char *path : paths) {
850 path_data->paths.append(path);
852 path_data->file_types.append(ED_path_extension_type(path));
853 }
854
855 path_data->tooltip = path_data->paths[0];
856
857 if (path_data->paths.size() > 1) {
858 std::string path_count = std::to_string(path_data->paths.size());
859 path_data->tooltip = fmt::format(TIP_("Dragging {} files"), path_count);
860 }
861
862 return path_data;
863}
864
865static void wm_drag_free_path_data(wmDragPath **path_data)
866{
867 MEM_delete(*path_data);
868 *path_data = nullptr;
869}
870
871const char *WM_drag_get_single_path(const wmDrag *drag)
872{
873 if (drag->type != WM_DRAG_PATH) {
874 return nullptr;
875 }
876
877 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
878 return path_data->paths[0].c_str();
879}
880
881const char *WM_drag_get_single_path(const wmDrag *drag, int file_type)
882{
883 if (drag->type != WM_DRAG_PATH) {
884 return nullptr;
885 }
886 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
887 const blender::Span<int> file_types = path_data->file_types;
888
889 const auto *itr = std::find_if(
890 file_types.begin(), file_types.end(), [file_type](const int file_fype_test) {
891 return file_fype_test & file_type;
892 });
893
894 if (itr == file_types.end()) {
895 return nullptr;
896 }
897 const int index = itr - file_types.begin();
898 return path_data->paths[index].c_str();
899}
900
901bool WM_drag_has_path_file_type(const wmDrag *drag, int file_type)
902{
903 if (drag->type != WM_DRAG_PATH) {
904 return false;
905 }
906 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
907 return bool(path_data->file_types_bit_flag & file_type);
908}
909
911{
912 if (drag->type != WM_DRAG_PATH) {
914 }
915
916 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
917 return path_data->paths.as_span();
918}
919
921{
922 if (drag->type != WM_DRAG_PATH) {
923 return 0;
924 }
925
926 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
927 return path_data->file_types[0];
928}
929
930const std::string &WM_drag_get_string(const wmDrag *drag)
931{
933 const std::string *str = static_cast<const std::string *>(drag->poin);
934 return *str;
935}
936
937std::string WM_drag_get_string_firstline(const wmDrag *drag)
938{
940 const std::string *str = static_cast<const std::string *>(drag->poin);
941 const size_t str_eol = str->find('\n');
942 if (str_eol != std::string::npos) {
943 return str->substr(0, str_eol);
944 }
945 return *str;
946}
947
948/* ************** draw ***************** */
949
950static void wm_drop_operator_draw(const blender::StringRef name, int x, int y)
951{
952 const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
953
954 /* Use the theme settings from tooltips. */
955 const bTheme *btheme = UI_GetTheme();
956 const uiWidgetColors *wcol = &btheme->tui.wcol_tooltip;
957
958 float col_fg[4], col_bg[4];
959 rgba_uchar_to_float(col_fg, wcol->text);
960 rgba_uchar_to_float(col_bg, wcol->inner);
961
962 UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg);
963}
964
965static void wm_drop_redalert_draw(const blender::StringRef redalert_str, int x, int y)
966{
967 const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
968 const bTheme *btheme = UI_GetTheme();
969 const uiWidgetColors *wcol = &btheme->tui.wcol_tooltip;
970
971 float col_fg[4], col_bg[4];
973 rgba_uchar_to_float(col_bg, wcol->inner);
974
975 UI_fontstyle_draw_simple_backdrop(fstyle, x, y, redalert_str, col_fg, col_bg);
976}
977
979{
980 switch (drag->type) {
981 case WM_DRAG_ID: {
982 ID *id = WM_drag_get_local_ID(drag, 0);
983 bool single = BLI_listbase_is_single(&drag->ids);
984
985 if (single) {
986 return id->name + 2;
987 }
988 if (id) {
989 return BKE_idtype_idcode_to_name_plural(GS(id->name));
990 }
991 break;
992 }
993 case WM_DRAG_ASSET: {
994 const wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0);
995 return asset_drag->asset->get_name().c_str();
996 }
997 case WM_DRAG_PATH: {
998 const wmDragPath *path_drag_data = static_cast<const wmDragPath *>(drag->poin);
999 return path_drag_data->tooltip.c_str();
1000 }
1001 case WM_DRAG_NAME:
1002 return static_cast<const char *>(drag->poin);
1003 default:
1004 break;
1005 }
1006 return "";
1007}
1008
1010{
1011 return round_fl_to_int(drag->imb->x * drag->imbuf_scale);
1012}
1013
1015{
1016 return round_fl_to_int(drag->imb->y * drag->imbuf_scale);
1017}
1018
1019static void wm_drag_draw_icon(bContext * /*C*/, wmWindow * /*win*/, wmDrag *drag, const int xy[2])
1020{
1021 int x, y;
1022
1023 /* This could also get the preview image of an ID when dragging one. But the big preview icon may
1024 * actually not always be wanted, for example when dragging objects in the Outliner it gets in
1025 * the way). So make the drag user set an image buffer explicitly (e.g. through
1026 * #UI_but_drag_attach_image()). */
1027
1028 if (drag->imb) {
1029 x = xy[0] - (wm_drag_imbuf_icon_width_get(drag) / 2);
1030 y = xy[1] - (wm_drag_imbuf_icon_height_get(drag) / 2);
1031
1032 const float col[4] = {1.0f, 1.0f, 1.0f, 0.65f}; /* This blends texture. */
1035 x,
1036 y,
1037 drag->imb->x,
1038 drag->imb->y,
1039 GPU_RGBA8,
1040 false,
1041 drag->imb->byte_buffer.data,
1042 drag->imbuf_scale,
1043 drag->imbuf_scale,
1044 1.0f,
1045 1.0f,
1046 col);
1047 }
1048 else {
1049 int padding = 4 * UI_SCALE_FAC;
1050 x = xy[0] - 2 * padding;
1051 y = xy[1] - 2 * UI_SCALE_FAC;
1052
1053 const uchar text_col[] = {255, 255, 255, 255};
1055 x, y, drag->icon, UI_INV_SCALE_FAC, 0.8, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT);
1056 }
1057}
1058
1059static void wm_drag_draw_item_name(wmDrag *drag, const int x, const int y)
1060{
1061 const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
1062 const uchar text_col[] = {255, 255, 255, 255};
1063 UI_fontstyle_draw_simple(fstyle, x, y, WM_drag_get_item_name(drag), text_col);
1064}
1065
1066void WM_drag_draw_item_name_fn(bContext * /*C*/, wmWindow *win, wmDrag *drag, const int xy[2])
1067{
1068 int x = xy[0] + 10 * UI_SCALE_FAC;
1069 int y = xy[1] + 1 * UI_SCALE_FAC;
1070
1071 /* Needs zero offset here or it looks blurry. #128112. */
1072 wmWindowViewport_ex(win, 0.0f);
1073 wm_drag_draw_item_name(drag, x, y);
1074}
1075
1076static void wm_drag_draw_tooltip(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
1077{
1078 if (!CTX_wm_region(C)) {
1079 /* Some callbacks require the region. */
1080 return;
1081 }
1082 int iconsize = UI_ICON_SIZE;
1083 int padding = 4 * UI_SCALE_FAC;
1084 blender::StringRef tooltip = drag->drop_state.tooltip;
1085 const bool has_disabled_info = drag->drop_state.disabled_info &&
1086 drag->drop_state.disabled_info[0];
1087 if (tooltip.is_empty() && !has_disabled_info) {
1088 return;
1089 }
1090
1091 const int winsize_y = WM_window_native_pixel_y(win);
1092 int x, y;
1093 if (drag->imb) {
1094 const int icon_width = wm_drag_imbuf_icon_width_get(drag);
1095 const int icon_height = wm_drag_imbuf_icon_height_get(drag);
1096
1097 x = xy[0] - (icon_width / 2);
1098
1099 if (xy[1] + (icon_height / 2) + padding + iconsize < winsize_y) {
1100 y = xy[1] + (icon_height / 2) + padding;
1101 }
1102 else {
1103 y = xy[1] - (icon_height / 2) - padding - iconsize - padding - iconsize;
1104 }
1105 }
1106 else {
1107 x = xy[0] - 2 * padding;
1108
1109 if (xy[1] + iconsize + iconsize < winsize_y) {
1110 y = (xy[1] + iconsize) + padding;
1111 }
1112 else {
1113 y = (xy[1] - iconsize) - padding;
1114 }
1115 }
1116
1117 if (!tooltip.is_empty()) {
1118 wm_drop_operator_draw(tooltip, x, y);
1119 }
1120 else if (has_disabled_info) {
1122 }
1123}
1124
1125static void wm_drag_draw_default(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
1126{
1127 int xy_tmp[2] = {UNPACK2(xy)};
1128
1129 /* Image or icon. */
1130 wm_drag_draw_icon(C, win, drag, xy_tmp);
1131
1132 /* Item name. */
1133 if (drag->imb) {
1134 int iconsize = UI_ICON_SIZE;
1135 xy_tmp[0] = xy[0] - (wm_drag_imbuf_icon_width_get(drag) / 2);
1136 xy_tmp[1] = xy[1] - (wm_drag_imbuf_icon_height_get(drag) / 2) - iconsize;
1137 }
1138 else {
1139 xy_tmp[0] = xy[0] + 10 * UI_SCALE_FAC;
1140 xy_tmp[1] = xy[1] + 1 * UI_SCALE_FAC;
1141 }
1142 wm_drag_draw_item_name(drag, UNPACK2(xy_tmp));
1143
1144 /* Operator name with round-box. */
1145 wm_drag_draw_tooltip(C, win, drag, xy);
1146}
1147
1148void WM_drag_draw_default_fn(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
1149{
1150 wm_drag_draw_default(C, win, drag, xy);
1151}
1152
1154{
1155 const int *xy = win->eventstate->xy;
1156
1157 int xy_buf[2];
1159 wm_cursor_position_get(win, &xy_buf[0], &xy_buf[1]))
1160 {
1161 xy = xy_buf;
1162 }
1163
1164 bScreen *screen = CTX_wm_screen(C);
1165 /* To start with, use the area and region under the mouse cursor, just like event handling. The
1166 * operator context may still override it. */
1169 /* Will be overridden and unset eventually. */
1171
1173
1174 /* Should we support multi-line drag draws? Maybe not, more types mixed won't work well. */
1176 LISTBASE_FOREACH (wmDrag *, drag, &wm->drags) {
1177 if (drag->drop_state.active_dropbox) {
1180 CTX_store_set(C, drag->drop_state.ui_context.get());
1181
1182 if (region && drag->drop_state.active_dropbox->draw_in_view) {
1183 wmViewport(&region->winrct);
1184 drag->drop_state.active_dropbox->draw_in_view(C, win, drag, xy);
1185 wmWindowViewport(win);
1186 }
1187
1188 /* Drawing should be allowed to assume the context from handling and polling (that's why we
1189 * restore it above). */
1191 drag->drop_state.active_dropbox->draw_droptip(C, win, drag, xy);
1192 continue;
1193 }
1194 }
1195 else if (region) {
1196 CTX_wm_area_set(C, area);
1197 CTX_wm_region_set(C, region);
1198 }
1199
1200 /* Needs zero offset here or it looks blurry. #128112. */
1201 wmWindowViewport_ex(win, 0.0f);
1202 wm_drag_draw_default(C, win, drag, xy);
1203 }
1205 CTX_wm_area_set(C, nullptr);
1206 CTX_wm_region_set(C, nullptr);
1207 CTX_store_set(C, nullptr);
1208}
Main runtime representation of an asset.
void immDrawPixelsTexTiled_scaling(IMMDrawPixelsTexState *state, float x, float y, int img_w, int img_h, eGPUTextureFormat gpu_format, bool use_filter, const void *rect, float scaleX, float scaleY, float xzoom, float yzoom, const float color[4])
Definition glutil.cc:301
IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin)
Definition glutil.cc:40
blender::Vector< PointerRNA > CTX_data_collection_get(const bContext *C, const char *member)
bScreen * CTX_wm_screen(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
const char * CTX_wm_operator_poll_msg_get(bContext *C, bool *r_free)
void CTX_store_set(bContext *C, const bContextStore *store)
void CTX_wm_area_set(bContext *C, ScrArea *area)
void CTX_wm_region_set(bContext *C, ARegion *region)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
#define G_MAIN
void IDP_FreeProperty(IDProperty *prop)
Definition idprop.cc:1227
const char * BKE_idtype_idcode_to_name_plural(short idcode)
Definition idtype.cc:175
void BKE_id_free_us(Main *bmain, void *idv) ATTR_NONNULL()
void id_us_plus(ID *id)
Definition lib_id.cc:351
ARegion * BKE_area_find_region_xy(const ScrArea *area, int regiontype, const int xy[2]) ATTR_NONNULL(3)
Definition screen.cc:844
ScrArea ScrArea * BKE_screen_find_area_xy(const bScreen *screen, int spacetype, const int xy[2]) ATTR_NONNULL(1
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:269
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void void BLI_INLINE bool BLI_listbase_is_single(const struct ListBase *lb)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:251
MINLINE int round_fl_to_int(float a)
void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define STRNCPY_UTF8(dst, src)
unsigned char uchar
unsigned int uint
#define UNPACK2(a)
#define STREQLEN(a, b, n)
#define ELEM(...)
external readfile function prototypes.
@ BLO_LIBLINK_APPEND_RECURSIVE
@ BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR
@ BLO_LIBLINK_APPEND_LOCAL_ID_REUSE
#define TIP_(msgid)
ID_Type
eAssetImportMethod
@ ASSET_IMPORT_LINK
@ ASSET_IMPORT_APPEND_REUSE
@ ASSET_IMPORT_APPEND
#define RGN_TYPE_ANY
#define RGN_TYPE_NUM
#define SPACE_TYPE_NUM
struct AssetRepresentationHandle AssetRepresentationHandle
eFileSel_Params_Flag
@ FILE_ACTIVE_COLLECTION
@ FILE_RELPATH
@ FILE_AUTOSELECT
#define SPACE_TYPE_ANY
#define UI_SCALE_FAC
#define UI_INV_SCALE_FAC
#define UI_ICON_SIZE
#define KMAP_MAX_NAME
int ED_path_extension_type(const char *path)
Definition filelist.cc:2776
ARegion * ED_area_find_region_xy_visual(const ScrArea *area, int regiontype, const int event_xy[2])
#define ED_screen_areas_iter(win, screen, area_name)
Definition ED_screen.hh:281
void ED_region_tag_redraw_no_rebuild(ARegion *region)
Definition area.cc:653
GHOST C-API function and type declarations.
@ GHOST_kGrabWrap
@ GHOST_kGrabHide
@ GPU_SHADER_3D_IMAGE_COLOR
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str, const uchar col[4])
uiBut * UI_region_active_but_get(const ARegion *region)
void UI_fontstyle_draw_simple_backdrop(const uiFontStyle *fs, float x, float y, blender::StringRef str, const float col_fg[4], const float col_bg[4])
#define UI_FSTYLE_WIDGET
const bContextStore * UI_but_context_get(const uiBut *but)
#define UI_NO_ICON_OVERLAY_TEXT
void UI_icon_draw_ex(float x, float y, int icon_id, float aspect, float alpha, float desaturate, const uchar mono_color[4], bool mono_border, const IconTextOverlay *text_overlay, const bool inverted=false)
@ TH_REDALERT
void UI_GetThemeColor4fv(int colorid, float col[4])
bTheme * UI_GetTheme()
eWM_DragFlags
Definition WM_types.hh:1179
@ WM_DRAG_FREE_DATA
Definition WM_types.hh:1181
wmOperatorCallContext
Definition WM_types.hh:216
@ WM_OP_INVOKE_DEFAULT
Definition WM_types.hh:218
eWM_DragDataType
Definition WM_types.hh:1152
@ WM_DRAG_PATH
Definition WM_types.hh:1160
@ WM_DRAG_ASSET_LIST
Definition WM_types.hh:1158
@ WM_DRAG_GREASE_PENCIL_LAYER
Definition WM_types.hh:1173
@ WM_DRAG_STRING
Definition WM_types.hh:1169
@ WM_DRAG_ASSET_CATALOG
Definition WM_types.hh:1172
@ WM_DRAG_NAME
Definition WM_types.hh:1161
@ WM_DRAG_ASSET
Definition WM_types.hh:1154
@ WM_DRAG_ID
Definition WM_types.hh:1153
std::string(*)(bContext *C, wmDrag *drag, const int xy[2], wmDropBox *drop) WMDropboxTooltipFunc
Definition WM_types.hh:1235
constexpr const T * end() const
Definition BLI_span.hh:225
constexpr const T * begin() const
Definition BLI_span.hh:221
constexpr bool is_empty() const
constexpr const char * c_str() const
int64_t size() const
void append(const T &value)
Span< T > as_span() const
#define printf
RAYTRACE_GROUP_SIZE additional_info("eevee_shared", "eevee_gbuffer_data", "eevee_global_ubo", "eevee_sampling_data", "eevee_utility_texture", "eevee_hiz_data", "draw_view") .specialization_constant(Type RAYTRACE_GROUP_SIZE in_sh_0_tx in_sh_2_tx screen_normal_tx GPU_RGBA8
#define str(s)
uint col
uint padding(uint offset, uint alignment)
#define GS(x)
Definition iris.cc:202
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
static ulong state[N]
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
The meta-data of an asset. By creating and giving this for a data-block (ID.asset_data),...
Definition DNA_ID.h:413
struct AssetMetaData * asset_data
Definition DNA_ID.h:422
ImBufByteBuffer byte_buffer
void * first
ID * owner_id
Definition RNA_types.hh:40
StructRNA * type
Definition RNA_types.hh:41
void * data
Definition RNA_types.hh:42
uiWidgetColors wcol_tooltip
unsigned char inner[4]
unsigned char text[4]
const char * disabled_info
Definition WM_types.hh:1272
std::unique_ptr< bContextStore > ui_context
Definition WM_types.hh:1265
wmDropBox * active_dropbox
Definition WM_types.hh:1248
wmDragAsset * external_info
Definition WM_types.hh:1215
union wmDragAssetListItem::@1405 asset_data
const AssetRepresentationHandle * asset
Definition WM_types.hh:1195
int import_method
Definition WM_types.hh:1194
ID * from_parent
Definition WM_types.hh:1190
int file_types_bit_flag
Definition WM_types.hh:1226
blender::Vector< int > file_types
Definition WM_types.hh:1224
blender::Vector< std::string > paths
Definition WM_types.hh:1222
std::string tooltip
Definition WM_types.hh:1227
float imbuf_scale
Definition WM_types.hh:1287
eWM_DragDataType type
Definition WM_types.hh:1282
const ImBuf * imb
Definition WM_types.hh:1286
void * poin
Definition WM_types.hh:1283
int icon
Definition WM_types.hh:1281
ListBase ids
Definition WM_types.hh:1294
ListBase asset_items
Definition WM_types.hh:1296
wmDragActiveDropState drop_state
Definition WM_types.hh:1289
eWM_DragFlags flags
Definition WM_types.hh:1291
ListBase dropboxes
char idname[KMAP_MAX_NAME]
wmDropBoxMap * prev
wmDropBoxMap * next
WMDropboxTooltipFunc tooltip
Definition WM_types.hh:1353
IDProperty * properties
Definition WM_types.hh:1366
void * draw_data
Definition WM_types.hh:1350
bool(* poll)(bContext *C, wmDrag *drag, const wmEvent *event)
Definition WM_types.hh:1311
void(* on_drag_start)(bContext *C, wmDrag *drag)
Definition WM_types.hh:1316
PointerRNA * ptr
Definition WM_types.hh:1368
wmOperatorType * ot
Definition WM_types.hh:1361
void(* on_exit)(wmDropBox *drop, wmDrag *drag)
Definition WM_types.hh:1323
void(* on_enter)(wmDropBox *drop, wmDrag *drag)
Definition WM_types.hh:1319
void(* cancel)(Main *bmain, wmDrag *drag, wmDropBox *drop)
Definition WM_types.hh:1332
char opname[64]
Definition WM_types.hh:1363
void(* draw_in_view)(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
Definition WM_types.hh:1347
void(* draw_droptip)(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
Definition WM_types.hh:1339
void(* copy)(bContext *C, wmDrag *drag, wmDropBox *drop)
Definition WM_types.hh:1326
short custom
Definition WM_types.hh:758
int xy[2]
Definition WM_types.hh:726
StructRNA * srna
Definition WM_types.hh:1080
struct wmEvent * eventstate
void WM_cursor_modal_set(wmWindow *win, int val)
void WM_cursor_modal_restore(wmWindow *win)
@ WM_CURSOR_DEFAULT
Definition wm_cursors.hh:15
@ WM_CURSOR_STOP
Definition wm_cursors.hh:18
static void wm_drop_item_clear_runtime(wmDropBox *drop)
AssetMetaData * WM_drag_get_asset_meta_data(const wmDrag *drag, int idcode)
void wm_dropbox_free()
static void wm_drop_update_active(bContext *C, wmDrag *drag, const wmEvent *event)
wmDropBox * WM_dropbox_add(ListBase *lb, const char *idname, bool(*poll)(bContext *C, wmDrag *drag, const wmEvent *event), void(*copy)(bContext *C, wmDrag *drag, wmDropBox *drop), void(*cancel)(Main *bmain, wmDrag *drag, wmDropBox *drop), WMDropboxTooltipFunc tooltip)
void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop)
void WM_drag_draw_item_name_fn(bContext *, wmWindow *win, wmDrag *drag, const int xy[2])
static void wm_drag_draw_icon(bContext *, wmWindow *, wmDrag *drag, const int xy[2])
static void wm_drag_free_asset_data(wmDragAsset **asset_data)
static void wm_drop_operator_draw(const blender::StringRef name, int x, int y)
wmDragAsset * WM_drag_create_asset_data(const blender::asset_system::AssetRepresentation *asset, int import_method)
static void wm_drop_redalert_draw(const blender::StringRef redalert_str, int x, int y)
void WM_drag_free_imported_drag_ID(Main *bmain, wmDrag *drag, wmDropBox *drop)
Free asset ID imported for canceled drop.
static void wm_dropbox_item_update_ot(wmDropBox *drop)
static std::string dropbox_tooltip(bContext *C, wmDrag *drag, const int xy[2], wmDropBox *drop)
bool WM_drag_asset_will_import_linked(const wmDrag *drag)
ID * WM_drag_asset_id_import(const bContext *C, wmDragAsset *asset_drag, const int flag_extra)
static void wm_drag_draw_tooltip(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
static wmDropBox * dropbox_active(bContext *C, ListBase *handlers, wmDrag *drag, const wmEvent *event)
static void wm_drag_draw_default(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
wmDragPath * WM_drag_create_path_data(blender::Span< const char * > paths)
void WM_event_start_drag(bContext *C, int icon, eWM_DragDataType type, void *poin, uint flags)
const char * WM_drag_get_item_name(wmDrag *drag)
void wm_drags_draw(bContext *C, wmWindow *win)
void WM_drag_add_asset_list_item(wmDrag *drag, const blender::asset_system::AssetRepresentation *asset)
wmOperatorCallContext wm_drop_operator_context_get(const wmDropBox *)
void WM_drag_free(wmDrag *drag)
void WM_event_start_prepared_drag(bContext *C, wmDrag *drag)
const std::string & WM_drag_get_string(const wmDrag *drag)
blender::Span< std::string > WM_drag_get_paths(const wmDrag *drag)
void wm_drop_end(bContext *C, wmDrag *, wmDropBox *)
wmDragAssetCatalog * WM_drag_get_asset_catalog_data(const wmDrag *drag)
void wm_drags_check_ops(bContext *C, const wmEvent *event)
void WM_drag_draw_default_fn(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
int WM_drag_get_path_file_type(const wmDrag *drag)
bool WM_drag_is_ID_type(const wmDrag *drag, int idcode)
const char * WM_drag_get_single_path(const wmDrag *drag)
ID * WM_drag_get_local_ID_or_import_from_asset(const bContext *C, const wmDrag *drag, int idcode)
static int wm_drag_imbuf_icon_height_get(const wmDrag *drag)
wmDrag * WM_drag_data_create(bContext *C, int icon, eWM_DragDataType type, void *poin, uint flags)
void WM_dropbox_update_ot()
static wmDropBox * wm_dropbox_active(bContext *C, wmDrag *drag, const wmEvent *event)
ID * WM_drag_get_local_ID_from_event(const wmEvent *event, short idcode)
void wm_drags_exit(wmWindowManager *wm, wmWindow *win)
void WM_event_drag_image(wmDrag *drag, const ImBuf *imb, float scale)
ListBase * WM_dropboxmap_find(const char *idname, int spaceid, int regionid)
static void wm_dropbox_invoke(bContext *C, wmDrag *drag)
static void wm_drop_item_free_data(wmDropBox *drop)
std::string WM_drag_get_string_firstline(const wmDrag *drag)
void WM_drag_data_free(eWM_DragDataType dragtype, void *poin)
void WM_drag_free_list(ListBase *lb)
wmDragAsset * WM_drag_get_asset_data(const wmDrag *drag, int idcode)
static ListBase dropboxes
void WM_drag_add_local_ID(wmDrag *drag, ID *id, ID *from_parent)
static std::unique_ptr< bContextStore > wm_drop_ui_context_create(const bContext *C)
static void wm_drag_draw_item_name(wmDrag *drag, const int x, const int y)
const ListBase * WM_drag_asset_list_get(const wmDrag *drag)
static int wm_drag_imbuf_icon_width_get(const wmDrag *drag)
static void wm_drag_free_path_data(wmDragPath **path_data)
bool WM_drag_has_path_file_type(const wmDrag *drag, int file_type)
ID * WM_drag_get_local_ID(const wmDrag *drag, short idcode)
int xy[2]
Definition wm_draw.cc:170
bool WM_operator_poll_context(bContext *C, wmOperatorType *ot, short context)
void WM_event_add_mousemove(wmWindow *win)
@ WM_HANDLER_TYPE_DROPBOX
@ EVT_DATA_DRAGDROP
PointerRNA * ptr
Definition wm_files.cc:4126
wmOperatorType * ot
Definition wm_files.cc:4125
ID * WM_operator_properties_id_lookup_from_name_or_session_uid(Main *bmain, PointerRNA *ptr, const ID_Type type)
std::string WM_operatortype_name(wmOperatorType *ot, PointerRNA *properties)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *opstring)
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
void WM_operator_properties_free(PointerRNA *ptr)
void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context)
void wmViewport(const rcti *winrct)
void wmWindowViewport(const wmWindow *win)
void wmWindowViewport_ex(const wmWindow *win, float offset)
blender::int2 WM_window_native_pixel_size(const wmWindow *win)
bool wm_cursor_position_get(wmWindow *win, int *r_x, int *r_y)
int WM_window_native_pixel_y(const wmWindow *win)
wmWindow * WM_window_find_under_cursor(wmWindow *win, const int event_xy[2], int r_event_xy_other[2])
bScreen * WM_window_get_active_screen(const wmWindow *win)
uint8_t flag
Definition wm_window.cc:138