Blender V5.0
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
10
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_listbase.h"
25#include "BLI_math_color.h"
26#include "BLI_path_utils.hh"
27#include "BLI_string.h"
28#include "BLI_string_utf8.h"
29
30#include "BIF_glutil.hh"
31
32#include "BKE_context.hh"
33#include "BKE_global.hh"
34#include "BKE_idprop.hh"
35#include "BKE_idtype.hh"
36#include "BKE_lib_id.hh"
37#include "BKE_main.hh"
38#include "BKE_preview_image.hh"
39#include "BKE_screen.hh"
40
41#include "BLO_readfile.hh"
42
43#include "ED_fileselect.hh"
44#include "ED_screen.hh"
45
46#include "GPU_shader_builtin.hh"
47#include "GPU_state.hh"
48
49#include "IMB_imbuf.hh"
50#include "IMB_imbuf_types.hh"
51
52#include "GHOST_Types.h"
53
54#include "UI_interface.hh"
55#include "UI_interface_icons.hh"
56#include "UI_resources.hh"
57
58#include "RNA_access.hh"
59
60#include "WM_api.hh"
61#include "WM_types.hh"
62#include "wm_event_system.hh"
63#include "wm_window.hh"
64
65#include <fmt/format.h>
66/* ****************************************************** */
67
68static ListBase dropboxes = {nullptr, nullptr};
69
70static void wm_drag_free_asset_data(wmDragAsset **asset_data);
71static void wm_drag_free_path_data(wmDragPath **path_data);
72
73static void wm_drop_item_free_data(wmDropBox *drop);
74static void wm_drop_item_clear_runtime(wmDropBox *drop);
75
78
79/* Drop box maps are stored global for now. */
80/* These are part of blender's UI/space specs, and not like keymaps. */
81/* When editors become configurable, they can add their own dropbox definitions. */
82
90
91ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid)
92{
94 if (dm->spaceid == spaceid && dm->regionid == regionid) {
95 if (STREQLEN(idname, dm->idname, KMAP_MAX_NAME)) {
96 return &dm->dropboxes;
97 }
98 }
99 }
100
102 STRNCPY_UTF8(dm->idname, idname);
103 dm->spaceid = spaceid;
104 dm->regionid = regionid;
106
107 return &dm->dropboxes;
108}
109
111 const char *idname,
112 bool (*poll)(bContext *C, wmDrag *drag, const wmEvent *event),
113 void (*copy)(bContext *C, wmDrag *drag, wmDropBox *drop),
114 void (*cancel)(Main *bmain, wmDrag *drag, wmDropBox *drop),
115 WMDropboxTooltipFunc tooltip)
116{
117 wmOperatorType *ot = WM_operatortype_find(idname, true);
118 if (ot == nullptr) {
119 printf("Error: dropbox with unknown operator: %s\n", idname);
120 return nullptr;
121 }
122
123 wmDropBox *drop = MEM_callocN<wmDropBox>(__func__);
124 drop->poll = poll;
125 drop->copy = copy;
126 drop->cancel = cancel;
127 drop->tooltip = tooltip;
128 drop->ot = ot;
129 STRNCPY(drop->opname, idname);
130
131 WM_operator_properties_alloc(&(drop->ptr), &(drop->properties), idname);
133
134 /* Signal for no context, see #STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID. */
135 drop->ptr->owner_id = nullptr;
136
137 BLI_addtail(lb, drop);
138
139 return drop;
140}
141
143{
144 /* NOTE(@ideasman42): this closely follows #wm_keymap_item_properties_update_ot.
145 * `keep_properties` is implied because drop boxes aren't dynamically added & removed.
146 * It's possible in the future drop-boxes can be (un)registered by scripts.
147 * In this case we might want to remove drop-boxes that point to missing operators. */
149 if (ot == nullptr) {
150 /* Allow for the operator to be added back and re-validated, keep it's properties. */
152 drop->ot = nullptr;
153 return;
154 }
155
156 if (drop->ptr == nullptr) {
157 WM_operator_properties_alloc(&(drop->ptr), &(drop->properties), drop->opname);
159 }
160 else {
161 if (ot->srna != drop->ptr->type) {
163 if (drop->properties) {
164 drop->ptr->data = drop->properties;
165 }
167 }
168 }
169
170 if (drop->ptr) {
171 drop->ptr->owner_id = nullptr;
172 }
173 drop->ot = ot;
174}
175
177{
179 LISTBASE_FOREACH (wmDropBox *, drop, &dm->dropboxes) {
181 }
182 }
183}
184
186{
187 if (drop->ptr) {
189 MEM_delete(drop->ptr);
190 drop->ptr = nullptr;
191 drop->properties = nullptr;
192 }
193 else if (drop->properties) {
195 drop->properties = nullptr;
196 }
197}
198
200{
201 IDProperty *properties = drop->properties;
202 drop->properties = nullptr;
203 if (drop->ptr) {
204 drop->ptr->data = nullptr;
205 }
207 drop->properties = properties;
208}
209
211{
212
214 LISTBASE_FOREACH (wmDropBox *, drop, &dm->dropboxes) {
216 }
217 BLI_freelistN(&dm->dropboxes);
218 }
219
221}
222
223/* *********************************** */
224
225static void wm_dropbox_invoke(bContext *C, wmDrag *drag)
226{
228
229 /* Create a bitmap flag matrix of all currently visible region and area types.
230 * Everything that isn't visible in the current window should not prefetch any data. */
231 bool area_region_tag[SPACE_TYPE_NUM][RGN_TYPE_NUM] = {{false}};
232
233 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
235 ED_screen_areas_iter (win, screen, area) {
236 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
237 if (region->runtime->visible) {
238 BLI_assert(area->spacetype < SPACE_TYPE_NUM);
239 BLI_assert(region->regiontype < RGN_TYPE_NUM);
240 area_region_tag[area->spacetype][region->regiontype] = true;
241 }
242 }
243 }
244 }
245
247 if (!area_region_tag[dm->spaceid][dm->regionid]) {
248 continue;
249 }
250 LISTBASE_FOREACH (wmDropBox *, drop, &dm->dropboxes) {
251 if (drag->drop_state.ui_context) {
252 CTX_store_set(C, drag->drop_state.ui_context.get());
253 }
254
255 if (drop->on_drag_start) {
256 drop->on_drag_start(C, drag);
257 }
258 CTX_store_set(C, nullptr);
259 }
260 }
261}
262
263wmDrag *WM_drag_data_create(bContext *C, int icon, eWM_DragDataType type, void *poin, uint flags)
264{
265 wmDrag *drag = MEM_new<wmDrag>(__func__);
266
267 /* Keep track of future multi-touch drag too, add a mouse-pointer id or so. */
268 /* If multiple drags are added, they're drawn as list. */
269
270 drag->flags = static_cast<eWM_DragFlags>(flags);
271 drag->icon = icon;
272 drag->type = type;
273 switch (type) {
274 case WM_DRAG_PATH:
275 drag->poin = poin;
276 drag->flags |= WM_DRAG_FREE_DATA;
277 break;
278 case WM_DRAG_ID:
279 if (poin) {
280 WM_drag_add_local_ID(drag, static_cast<ID *>(poin), nullptr);
281 }
282 break;
284 case WM_DRAG_ASSET:
286 /* Move ownership of poin to wmDrag. */
287 drag->poin = poin;
288 drag->flags |= WM_DRAG_FREE_DATA;
289 break;
290 /* The asset-list case is special: We get multiple assets from context and attach them to the
291 * drag item. */
292 case WM_DRAG_ASSET_LIST: {
293 blender::Vector<PointerRNA> asset_links = CTX_data_collection_get(C, "selected_assets");
294 for (const PointerRNA &ptr : asset_links) {
295 const AssetRepresentationHandle *asset = static_cast<const AssetRepresentationHandle *>(
296 ptr.data);
297 WM_drag_add_asset_list_item(drag, asset);
298 }
299 break;
300 }
301 default:
302 drag->poin = poin;
303 break;
304 }
305
306 return drag;
307}
308
310{
312
313 BLI_addtail(&wm->runtime->drags, drag);
314 wm_dropbox_invoke(C, drag);
315}
316
317void WM_event_start_drag(bContext *C, int icon, eWM_DragDataType type, void *poin, uint flags)
318{
319 wmDrag *drag = WM_drag_data_create(C, icon, type, poin, flags);
321}
322
324{
325 /* Turn off modal cursor for all windows. */
326 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
328 }
329
330 /* Active area should always redraw, even if canceled. */
331 int event_xy_target[2];
332 wmWindow *target_win = WM_window_find_under_cursor(win, win->eventstate->xy, event_xy_target);
333 if (target_win) {
334 const bScreen *screen = WM_window_get_active_screen(target_win);
336
337 /* Ensure the correct area cursor is restored. */
338 target_win->tag_cursor_refresh = true;
339 WM_event_add_mousemove(target_win);
340 }
341}
342
343static std::unique_ptr<bContextStore> wm_drop_ui_context_create(const bContext *C)
344{
346 if (!active_but) {
347 return nullptr;
348 }
349
350 const bContextStore *but_context = UI_but_context_get(active_but);
351 if (!but_context) {
352 return nullptr;
353 }
354
355 return std::make_unique<bContextStore>(*but_context);
356}
357
358void WM_event_drag_image(wmDrag *drag, const ImBuf *imb, float scale)
359{
360 drag->imb = imb;
361 drag->imbuf_scale = scale;
362}
363
365{
366 BLI_assert(drag->type == WM_DRAG_PATH);
367 const SpaceFile *sfile = CTX_wm_space_file(C);
368 if (!sfile) {
369 return;
370 }
372 sfile);
374 for (const std::string &path : selected_paths) {
375 paths.append(path.c_str());
376 }
377 if (paths.is_empty()) {
378 return;
379 }
380 WM_drag_data_free(drag->type, drag->poin);
381 drag->poin = WM_drag_create_path_data(paths);
382}
383
384void WM_event_drag_preview_icon(wmDrag *drag, int icon_id)
385{
386 BLI_assert_msg(!drag->imb, "Drag image and preview are mutually exclusive");
387 drag->preview_icon_id = icon_id;
388}
389
390void WM_drag_data_free(eWM_DragDataType dragtype, void *poin)
391{
392 /* Don't require all the callers to have a nullptr-check, just allow passing nullptr. */
393 if (!poin) {
394 return;
395 }
396
397 /* Not too nice, could become a callback. */
398 switch (dragtype) {
399 case WM_DRAG_ASSET: {
400 wmDragAsset *asset_data = static_cast<wmDragAsset *>(poin);
401 wm_drag_free_asset_data(&asset_data);
402 break;
403 }
404 case WM_DRAG_PATH: {
405 wmDragPath *path_data = static_cast<wmDragPath *>(poin);
406 wm_drag_free_path_data(&path_data);
407 break;
408 }
409 case WM_DRAG_STRING: {
410 std::string *str = static_cast<std::string *>(poin);
411 MEM_delete(str);
412 break;
413 }
414 default:
415 MEM_freeN(poin);
416 break;
417 }
418}
419
421{
424 }
425 if (drag->flags & WM_DRAG_FREE_DATA) {
426 WM_drag_data_free(drag->type, drag->poin);
427 }
428 drag->drop_state.ui_context.reset();
429 if (drag->drop_state.free_disabled_info) {
431 }
432 BLI_freelistN(&drag->ids);
434 if (asset_item->is_external) {
435 wm_drag_free_asset_data(&asset_item->asset_data.external_info);
436 }
437 BLI_freelinkN(&drag->asset_items, asset_item);
438 }
439 MEM_delete(drag);
440}
441
443{
444 while (wmDrag *drag = static_cast<wmDrag *>(BLI_pophead(lb))) {
445 WM_drag_free(drag);
446 }
447}
448
449static std::string dropbox_tooltip(bContext *C, wmDrag *drag, const int xy[2], wmDropBox *drop)
450{
451 if (drop->tooltip) {
452 return drop->tooltip(C, drag, xy, drop);
453 }
454 if (drop->ot) {
455 return WM_operatortype_name(drop->ot, drop->ptr);
456 }
457 return {};
458}
459
461 ListBase *handlers,
462 wmDrag *drag,
463 const wmEvent *event)
464{
465 if (drag->drop_state.free_disabled_info) {
467 }
468 drag->drop_state.disabled_info = nullptr;
469
470 LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) {
471 if (handler_base->type == WM_HANDLER_TYPE_DROPBOX) {
472 wmEventHandler_Dropbox *handler = (wmEventHandler_Dropbox *)handler_base;
473 if (handler->dropboxes) {
474 LISTBASE_FOREACH (wmDropBox *, drop, handler->dropboxes) {
475 if (drag->drop_state.ui_context) {
476 CTX_store_set(C, drag->drop_state.ui_context.get());
477 }
478
479 if (!drop->poll(C, drag, event)) {
480 /* If the drop's poll fails, don't set the disabled-info. This would be too aggressive.
481 * Instead show it only if the drop box could be used in principle, but the operator
482 * can't be executed. */
483 continue;
484 }
485
487 if (drop->ot && WM_operator_poll_context(C, drop->ot, opcontext)) {
488 /* Get dropbox tooltip now, #wm_drag_draw_tooltip can use a different draw context. */
489 drag->drop_state.tooltip = dropbox_tooltip(C, drag, event->xy, drop);
490 CTX_store_set(C, nullptr);
491 return drop;
492 }
493
494 /* Attempt to set the disabled hint when the poll fails. Will always be the last hint set
495 * when there are multiple failing polls (could allow multiple disabled-hints too). */
496 bool free_disabled_info = false;
497 const char *disabled_hint = CTX_wm_operator_poll_msg_get(C, &free_disabled_info);
498 if (disabled_hint) {
499 drag->drop_state.disabled_info = disabled_hint;
500 drag->drop_state.free_disabled_info = free_disabled_info;
501 }
502 }
503 }
504 }
505 }
506 CTX_store_set(C, nullptr);
507 return nullptr;
508}
509
510/* Return active operator tooltip/name when mouse is in box. */
511static wmDropBox *wm_dropbox_active(bContext *C, wmDrag *drag, const wmEvent *event)
512{
513 wmWindow *win = CTX_wm_window(C);
515 ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->xy);
516 wmDropBox *drop = nullptr;
517
518 if (area) {
519 ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_ANY, event->xy);
520 if (region) {
521 drop = dropbox_active(C, &region->runtime->handlers, drag, event);
522 }
523
524 if (!drop) {
525 drop = dropbox_active(C, &area->handlers, drag, event);
526 }
527 }
528 if (!drop) {
529 drop = dropbox_active(C, &win->handlers, drag, event);
530 }
531 return drop;
532}
533
537static void wm_drop_update_active(bContext *C, wmDrag *drag, const wmEvent *event)
538{
539 wmWindow *win = CTX_wm_window(C);
540 const blender::int2 win_size = WM_window_native_pixel_size(win);
541
542 /* For multi-window drags, we only do this if mouse inside. */
543 if (event->xy[0] < 0 || event->xy[1] < 0 || event->xy[0] > win_size[0] ||
544 event->xy[1] > win_size[1])
545 {
546 return;
547 }
548
549 /* Update UI context, before polling so polls can query this context. */
550 drag->drop_state.ui_context.reset();
552 drag->drop_state.tooltip = "";
553
554 wmDropBox *drop_prev = drag->drop_state.active_dropbox;
555 wmDropBox *drop = wm_dropbox_active(C, drag, event);
556 if (drop != drop_prev) {
557 if (drop_prev && drop_prev->on_exit) {
558 drop_prev->on_exit(drop_prev, drag);
559 BLI_assert(drop_prev->draw_data == nullptr);
560 }
561 if (drop && drop->on_enter) {
562 drop->on_enter(drop, drag);
563 }
564 drag->drop_state.active_dropbox = drop;
565 drag->drop_state.area_from = drop ? CTX_wm_area(C) : nullptr;
566 drag->drop_state.region_from = drop ? CTX_wm_region(C) : nullptr;
567 }
568
569 if (!drag->drop_state.active_dropbox) {
570 drag->drop_state.ui_context.reset();
571 }
572}
573
575{
577
578 if (drag->drop_state.ui_context) {
579 CTX_store_set(C, drag->drop_state.ui_context.get());
580 }
581
582 /* Optionally copy drag information to operator properties. Don't call it if the
583 * operator fails anyway, it might do more than just set properties (e.g.
584 * typically import an asset). */
585 if (drop->copy && WM_operator_poll_context(C, drop->ot, opcontext)) {
586 drop->copy(C, drag, drop);
587 }
588
590}
591
592void wm_drop_end(bContext *C, wmDrag * /*drag*/, wmDropBox * /*drop*/)
593{
594 CTX_store_set(C, nullptr);
595}
596
598{
600
601 bool any_active = false;
602 LISTBASE_FOREACH (wmDrag *, drag, &wm->runtime->drags) {
603 wm_drop_update_active(C, drag, event);
604
605 if (drag->drop_state.active_dropbox) {
606 any_active = true;
607 }
608 }
609
610 /* Change the cursor to display that dropping isn't possible here. But only if there is something
611 * being dragged actually. Cursor will be restored in #wm_drags_exit(). */
612 if (!BLI_listbase_is_empty(&wm->runtime->drags)) {
614 }
615}
616
621
622/* ************** IDs ***************** */
623
624void WM_drag_add_local_ID(wmDrag *drag, ID *id, ID *from_parent)
625{
626 /* Don't drag the same ID twice. */
627 LISTBASE_FOREACH (wmDragID *, drag_id, &drag->ids) {
628 if (drag_id->id == id) {
629 if (drag_id->from_parent == nullptr) {
630 drag_id->from_parent = from_parent;
631 }
632 return;
633 }
634 if (GS(drag_id->id->name) != GS(id->name)) {
635 BLI_assert_msg(0, "All dragged IDs must have the same type");
636 return;
637 }
638 }
639
640 /* Add to list. */
641 wmDragID *drag_id = MEM_callocN<wmDragID>(__func__);
642 drag_id->id = id;
643 drag_id->from_parent = from_parent;
644 BLI_addtail(&drag->ids, drag_id);
645}
646
647ID *WM_drag_get_local_ID(const wmDrag *drag, short idcode)
648{
649 if (drag->type != WM_DRAG_ID) {
650 return nullptr;
651 }
652
653 wmDragID *drag_id = static_cast<wmDragID *>(drag->ids.first);
654 if (!drag_id) {
655 return nullptr;
656 }
657
658 ID *id = drag_id->id;
659 return (idcode == 0 || GS(id->name) == idcode) ? id : nullptr;
660}
661
662ID *WM_drag_get_local_ID_from_event(const wmEvent *event, short idcode)
663{
664 if (event->custom != EVT_DATA_DRAGDROP) {
665 return nullptr;
666 }
667
668 ListBase *lb = static_cast<ListBase *>(event->customdata);
669 return WM_drag_get_local_ID(static_cast<const wmDrag *>(lb->first), idcode);
670}
671
672bool WM_drag_is_ID_type(const wmDrag *drag, int idcode)
673{
674 return WM_drag_get_local_ID(drag, idcode) || WM_drag_get_asset_data(drag, idcode);
675}
676
678 const AssetImportSettings &import_settings)
679{
680 wmDragAsset *asset_drag = MEM_new<wmDragAsset>(__func__);
681
682 asset_drag->asset = asset;
683 asset_drag->import_settings = import_settings;
684
685 return asset_drag;
686}
687
688static void wm_drag_free_asset_data(wmDragAsset **asset_data)
689{
690 if (*asset_data) {
691 MEM_delete(*asset_data);
692 *asset_data = nullptr;
693 }
694}
695
697{
698 if (drag->type != WM_DRAG_ASSET) {
699 return nullptr;
700 }
701
702 wmDragAsset *asset_drag = static_cast<wmDragAsset *>(drag->poin);
703 ID_Type asset_idcode = asset_drag->asset->get_id_type();
704 return ELEM(idcode, 0, asset_idcode) ? asset_drag : nullptr;
705}
706
708{
709 wmDragAsset *drag_asset = WM_drag_get_asset_data(drag, idcode);
710 if (drag_asset) {
711 return &drag_asset->asset->get_metadata();
712 }
713
714 ID *local_id = WM_drag_get_local_ID(drag, idcode);
715 if (local_id) {
716 return local_id->asset_data;
717 }
718
719 return nullptr;
720}
721
722ID *WM_drag_asset_id_import(const bContext *C, wmDragAsset *asset_drag, const int flag_extra)
723{
724 /* Only support passing in limited flags. */
725 BLI_assert(flag_extra == (flag_extra & FILE_AUTOSELECT));
726 /* #eFileSel_Params_Flag + #eBLOLibLinkFlags */
727 int flag = flag_extra | FILE_ACTIVE_COLLECTION;
728
729 const char *name = asset_drag->asset->get_name().c_str();
730 const std::string blend_path = asset_drag->asset->full_library_path();
731 const ID_Type idtype = asset_drag->asset->get_id_type();
732 const bool use_relative_path = asset_drag->asset->get_use_relative_path();
733
736 }
737
738 /* FIXME: Link/Append should happens in the operator called at the end of drop process, not from
739 * here. */
740
741 Main *bmain = CTX_data_main(C);
742 Scene *scene = CTX_data_scene(C);
743 ViewLayer *view_layer = CTX_data_view_layer(C);
744 View3D *view3d = CTX_wm_view3d(C);
745
746 switch (eAssetImportMethod(asset_drag->import_settings.method)) {
748 return WM_file_link_datablock(bmain,
749 scene,
750 view_layer,
751 view3d,
752 blend_path.c_str(),
753 idtype,
754 name,
755 flag | (use_relative_path ? FILE_RELPATH : 0));
757 return WM_file_link_datablock(bmain,
758 scene,
759 view_layer,
760 view3d,
761 blend_path.c_str(),
762 idtype,
763 name,
764 flag | (use_relative_path ? FILE_RELPATH : 0) |
767 return WM_file_append_datablock(bmain,
768 scene,
769 view_layer,
770 view3d,
771 blend_path.c_str(),
772 idtype,
773 name,
778 G_MAIN,
779 scene,
780 view_layer,
781 view3d,
782 blend_path.c_str(),
783 idtype,
784 name,
786 BLO_LIBLINK_APPEND_LOCAL_ID_REUSE | (use_relative_path ? FILE_RELPATH : 0));
787 }
788
790 return nullptr;
791}
792
794{
795 if (drag->type != WM_DRAG_ASSET) {
796 return false;
797 }
798
799 const wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0);
800 return asset_drag->import_settings.method == ASSET_IMPORT_LINK;
801}
802
804{
805 if (drag->type != WM_DRAG_ASSET) {
806 return false;
807 }
808
809 const wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0);
810 return asset_drag->import_settings.method == ASSET_IMPORT_PACK;
811}
812
814{
815 if (!ELEM(drag->type, WM_DRAG_ASSET, WM_DRAG_ID)) {
816 return nullptr;
817 }
818
819 if (drag->type == WM_DRAG_ID) {
820 return WM_drag_get_local_ID(drag, idcode);
821 }
822
823 wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, idcode);
824 if (!asset_drag) {
825 return nullptr;
826 }
827
828 /* Link/append the asset. */
829 return WM_drag_asset_id_import(C, asset_drag, 0);
830}
831
833{
834 if (drag->type != WM_DRAG_ASSET) {
835 return;
836 }
837
838 wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0);
839 if (!asset_drag) {
840 return;
841 }
842
843 ID_Type asset_id_type = asset_drag->asset->get_id_type();
844 /* Try to find the imported ID. For this to work either a "session_uid" or "name" property must
845 * have been defined (see #WM_operator_properties_id_lookup()). */
847 bmain, drop->ptr, asset_id_type);
848 if (id != nullptr) {
849 /* Do not delete the dragged ID if it has any user, otherwise if it is a 're-used' ID it will
850 * cause #95636. Note that we need first to add the user that we want to remove in
851 * #BKE_id_free_us. */
852 id_us_plus(id);
853 BKE_id_free_us(bmain, id);
854 }
855}
856
858{
859 if (drag->type != WM_DRAG_ASSET_CATALOG) {
860 return nullptr;
861 }
862
863 return static_cast<wmDragAssetCatalog *>(drag->poin);
864}
865
868{
870
871 /* No guarantee that the same asset isn't added twice. */
872
873 /* Add to list. */
875 ID *local_id = asset->local_id();
876 if (local_id) {
877 drag_asset->is_external = false;
878 drag_asset->asset_data.local_id = local_id;
879 }
880 else {
881 drag_asset->is_external = true;
882
883 AssetImportSettings import_settings{};
884 import_settings.method = ASSET_IMPORT_APPEND;
885 import_settings.use_instance_collections = false;
886
887 drag_asset->asset_data.external_info = WM_drag_create_asset_data(asset, import_settings);
888 }
889 BLI_addtail(&drag->asset_items, drag_asset);
890}
891
893{
894 if (drag->type != WM_DRAG_ASSET_LIST) {
895 return nullptr;
896 }
897
898 return &drag->asset_items;
899}
900
902{
903 BLI_assert(!paths.is_empty());
904 wmDragPath *path_data = MEM_new<wmDragPath>("wmDragPath");
905
906 for (const char *path : paths) {
907 path_data->paths.append(path);
908 const int type_flag = ED_path_extension_type(path);
909 path_data->file_types_bit_flag |= type_flag;
910 path_data->file_types.append(type_flag);
911 }
912
913 path_data->tooltip = path_data->paths[0];
914
915 if (path_data->paths.size() > 1) {
916 std::string path_count = std::to_string(path_data->paths.size());
917 path_data->tooltip = fmt::format(fmt::runtime(TIP_("Dragging {} files")), path_count);
918 }
919
920 return path_data;
921}
922
923static void wm_drag_free_path_data(wmDragPath **path_data)
924{
925 MEM_delete(*path_data);
926 *path_data = nullptr;
927}
928
929const char *WM_drag_get_single_path(const wmDrag *drag)
930{
931 if (drag->type != WM_DRAG_PATH) {
932 return nullptr;
933 }
934
935 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
936 return path_data->paths[0].c_str();
937}
938
939const char *WM_drag_get_single_path(const wmDrag *drag, int file_type)
940{
941 if (drag->type != WM_DRAG_PATH) {
942 return nullptr;
943 }
944 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
945 const blender::Span<int> file_types = path_data->file_types;
946
947 const auto *itr = std::find_if(
948 file_types.begin(), file_types.end(), [file_type](const int file_fype_test) {
949 return file_fype_test & file_type;
950 });
951
952 if (itr == file_types.end()) {
953 return nullptr;
954 }
955 const int index = itr - file_types.begin();
956 return path_data->paths[index].c_str();
957}
958
959bool WM_drag_has_path_file_type(const wmDrag *drag, int file_type)
960{
961 if (drag->type != WM_DRAG_PATH) {
962 return false;
963 }
964 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
965 return bool(path_data->file_types_bit_flag & file_type);
966}
967
969{
970 if (drag->type != WM_DRAG_PATH) {
972 }
973
974 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
975 return path_data->paths.as_span();
976}
977
979{
980 if (drag->type != WM_DRAG_PATH) {
981 return 0;
982 }
983
984 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
985 return path_data->file_types[0];
986}
987
988const std::string &WM_drag_get_string(const wmDrag *drag)
989{
991 const std::string *str = static_cast<const std::string *>(drag->poin);
992 return *str;
993}
994
995std::string WM_drag_get_string_firstline(const wmDrag *drag)
996{
998 const std::string *str = static_cast<const std::string *>(drag->poin);
999 const size_t str_eol = str->find('\n');
1000 if (str_eol != std::string::npos) {
1001 return str->substr(0, str_eol);
1002 }
1003 return *str;
1004}
1005
1006/* ************** draw ***************** */
1007
1009{
1010 const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
1011
1012 /* Use the theme settings from tooltips. */
1013 const bTheme *btheme = UI_GetTheme();
1014 const uiWidgetColors *wcol = &btheme->tui.wcol_tooltip;
1015
1016 float col_fg[4], col_bg[4];
1017 rgba_uchar_to_float(col_fg, wcol->text);
1018 rgba_uchar_to_float(col_bg, wcol->inner);
1019
1020 UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg);
1021}
1022
1023static void wm_drop_redalert_draw(const blender::StringRef redalert_str, int x, int y)
1024{
1025 const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
1026 const bTheme *btheme = UI_GetTheme();
1027 const uiWidgetColors *wcol = &btheme->tui.wcol_tooltip;
1028
1029 float col_fg[4], col_bg[4];
1031 rgba_uchar_to_float(col_bg, wcol->inner);
1032
1033 UI_fontstyle_draw_simple_backdrop(fstyle, x, y, redalert_str, col_fg, col_bg);
1034}
1035
1037{
1038 switch (drag->type) {
1039 case WM_DRAG_ID: {
1040 ID *id = WM_drag_get_local_ID(drag, 0);
1041 bool single = BLI_listbase_is_single(&drag->ids);
1042
1043 if (single) {
1044 return id->name + 2;
1045 }
1046 if (id) {
1048 }
1049 break;
1050 }
1051 case WM_DRAG_ASSET: {
1052 const wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0);
1053 return asset_drag->asset->get_name().c_str();
1054 }
1055 case WM_DRAG_PATH: {
1056 const wmDragPath *path_drag_data = static_cast<const wmDragPath *>(drag->poin);
1057 return path_drag_data->tooltip.c_str();
1058 }
1059 case WM_DRAG_NAME:
1060 return static_cast<const char *>(drag->poin);
1061 default:
1062 break;
1063 }
1064 return "";
1065}
1066
1068{
1069 return round_fl_to_int(drag->imb->x * drag->imbuf_scale);
1070}
1071
1073{
1074 return round_fl_to_int(drag->imb->y * drag->imbuf_scale);
1075}
1076
1078{
1080}
1081
1082static void wm_drag_draw_icon(bContext * /*C*/, wmWindow * /*win*/, wmDrag *drag, const int xy[2])
1083{
1084 int x, y;
1085
1086 if (const int64_t path_count = WM_drag_get_paths(drag).size(); path_count > 1) {
1087 /* Custom scale to improve path count readability. */
1088 const float scale = UI_SCALE_FAC * 1.15f;
1089 x = xy[0] - int(8.0f * scale);
1090 y = xy[1] - int(scale);
1091 const uchar text_col[] = {255, 255, 255, 255};
1092 IconTextOverlay text_overlay;
1093 UI_icon_text_overlay_init_from_count(&text_overlay, path_count);
1095 x, y, ICON_DOCUMENTS, 1.0f / scale, 1.0f, 0.0f, text_col, false, &text_overlay);
1096 }
1097 else if (drag->imb) {
1098 /* This could also get the preview image of an ID when dragging one. But the big preview icon
1099 * may actually not always be wanted, for example when dragging objects in the Outliner it gets
1100 * in the way). So make the drag user set an image buffer explicitly (e.g. through
1101 * #UI_but_drag_attach_image()). */
1102
1103 x = xy[0] - (wm_drag_imbuf_icon_width_get(drag) / 2);
1104 y = xy[1] - (wm_drag_imbuf_icon_height_get(drag) / 2);
1105
1106 const float col[4] = {1.0f, 1.0f, 1.0f, 0.65f}; /* This blends texture. */
1109 x,
1110 y,
1111 drag->imb->x,
1112 drag->imb->y,
1113 blender::gpu::TextureFormat::UNORM_8_8_8_8,
1114 false,
1115 drag->imb->byte_buffer.data,
1116 drag->imbuf_scale,
1117 drag->imbuf_scale,
1118 1.0f,
1119 1.0f,
1120 col);
1121 }
1122 else if (drag->preview_icon_id) {
1123 const int size = wm_drag_preview_icon_size_get();
1124 x = xy[0] - (size / 2);
1125 y = xy[1] - (size / 2);
1126
1127 UI_icon_draw_preview(x, y, drag->preview_icon_id, 1.0, 0.8, size);
1128 }
1129 else {
1130 int padding = 4 * UI_SCALE_FAC;
1131 x = xy[0] - 2 * padding;
1132 y = xy[1] - 2 * UI_SCALE_FAC;
1133
1134 const uchar text_col[] = {255, 255, 255, 255};
1136 x, y, drag->icon, UI_INV_SCALE_FAC, 0.8, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT);
1137 }
1138}
1139
1140static void wm_drag_draw_item_name(wmDrag *drag, const int x, const int y)
1141{
1142 const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
1143 const uchar text_col[] = {255, 255, 255, 255};
1144 UI_fontstyle_draw_simple(fstyle, x, y, WM_drag_get_item_name(drag), text_col);
1145}
1146
1147void WM_drag_draw_item_name_fn(bContext * /*C*/, wmWindow *win, wmDrag *drag, const int xy[2])
1148{
1149 int x = xy[0] + 10 * UI_SCALE_FAC;
1150 int y = xy[1] + 1 * UI_SCALE_FAC;
1151
1152 /* Needs zero offset here or it looks blurry. #128112. */
1153 wmWindowViewport_ex(win, 0.0f);
1154 wm_drag_draw_item_name(drag, x, y);
1155}
1156
1157static void wm_drag_draw_tooltip(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
1158{
1159 if (!CTX_wm_region(C)) {
1160 /* Some callbacks require the region. */
1161 return;
1162 }
1163 int iconsize = UI_ICON_SIZE;
1164 int padding = 4 * UI_SCALE_FAC;
1165 blender::StringRef tooltip = drag->drop_state.tooltip;
1166 const bool has_disabled_info = drag->drop_state.disabled_info &&
1167 drag->drop_state.disabled_info[0];
1168 if (tooltip.is_empty() && !has_disabled_info) {
1169 return;
1170 }
1171
1172 const int winsize_y = WM_window_native_pixel_y(win);
1173 int x, y;
1174 if (drag->imb) {
1175 const int icon_width = wm_drag_imbuf_icon_width_get(drag);
1176 const int icon_height = wm_drag_imbuf_icon_height_get(drag);
1177
1178 x = xy[0] - (icon_width / 2);
1179
1180 if (xy[1] + (icon_height / 2) + padding + iconsize < winsize_y) {
1181 y = xy[1] + (icon_height / 2) + padding;
1182 }
1183 else {
1184 y = xy[1] - (icon_height / 2) - padding - iconsize - padding - iconsize;
1185 }
1186 }
1187 if (WM_drag_get_paths(drag).size() > 1) {
1188 x = xy[0] - 2 * padding;
1189
1190 if (xy[1] + 2 * 1.15 * iconsize < winsize_y) {
1191 y = xy[1] + 1.15f * (iconsize + 6 * UI_SCALE_FAC);
1192 }
1193 else {
1194 y = xy[1] - 1.15f * (iconsize + padding);
1195 }
1196 }
1197 else if (drag->preview_icon_id) {
1198 const int size = wm_drag_preview_icon_size_get();
1199
1200 x = xy[0] - (size / 2);
1201
1202 if (xy[1] + (size / 2) + padding + iconsize < winsize_y) {
1203 y = xy[1] + (size / 2) + padding;
1204 }
1205 else {
1206 y = xy[1] - (size / 2) - padding - iconsize - padding - iconsize;
1207 }
1208 }
1209 else {
1210 x = xy[0] - 2 * padding;
1211
1212 if (xy[1] + iconsize + iconsize < winsize_y) {
1213 y = (xy[1] + iconsize) + padding;
1214 }
1215 else {
1216 y = (xy[1] - iconsize) - padding;
1217 }
1218 }
1219
1220 if (!tooltip.is_empty()) {
1221 wm_drop_operator_draw(tooltip, x, y);
1222 }
1223 else if (has_disabled_info) {
1225 }
1226}
1227
1228static void wm_drag_draw_default(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
1229{
1230 int xy_tmp[2] = {UNPACK2(xy)};
1231
1232 /* Image or icon. */
1233 wm_drag_draw_icon(C, win, drag, xy_tmp);
1234
1235 /* Item name. */
1236 if (drag->imb) {
1237 int iconsize = UI_ICON_SIZE;
1238 xy_tmp[0] = xy[0] - (wm_drag_imbuf_icon_width_get(drag) / 2);
1239 xy_tmp[1] = xy[1] - (wm_drag_imbuf_icon_height_get(drag) / 2) - iconsize;
1240 }
1241 else if (drag->preview_icon_id) {
1242 const int icon_size = UI_ICON_SIZE;
1243 const int preview_size = wm_drag_preview_icon_size_get();
1244 xy_tmp[0] = xy[0] - (preview_size / 2);
1245 xy_tmp[1] = xy[1] - (preview_size / 2) - icon_size;
1246 }
1247 else {
1248 xy_tmp[0] = xy[0] + 10 * UI_SCALE_FAC;
1249 xy_tmp[1] = xy[1] + 1 * UI_SCALE_FAC;
1250 }
1251 if (WM_drag_get_paths(drag).size() < 2) {
1252 wm_drag_draw_item_name(drag, UNPACK2(xy_tmp));
1253 }
1254
1255 /* Operator name with round-box. */
1256 wm_drag_draw_tooltip(C, win, drag, xy);
1257}
1258
1259void WM_drag_draw_default_fn(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
1260{
1261 wm_drag_draw_default(C, win, drag, xy);
1262}
1263
1265{
1266 const int *xy = win->eventstate->xy;
1267
1268 int xy_buf[2];
1270 wm_cursor_position_get(win, &xy_buf[0], &xy_buf[1]))
1271 {
1272 xy = xy_buf;
1273 }
1274
1275 bScreen *screen = CTX_wm_screen(C);
1276 /* To start with, use the area and region under the mouse cursor, just like event handling. The
1277 * operator context may still override it. */
1280 /* Will be overridden and unset eventually. */
1282
1284
1285 /* Should we support multi-line drag draws? Maybe not, more types mixed won't work well. */
1287 LISTBASE_FOREACH (wmDrag *, drag, &wm->runtime->drags) {
1288 if (drag->drop_state.active_dropbox) {
1291 CTX_store_set(C, drag->drop_state.ui_context.get());
1292
1293 if (region && drag->drop_state.active_dropbox->draw_in_view) {
1294 wmViewport(&region->winrct);
1295 drag->drop_state.active_dropbox->draw_in_view(C, win, drag, xy);
1296 wmWindowViewport(win);
1297 }
1298
1299 /* Drawing should be allowed to assume the context from handling and polling (that's why we
1300 * restore it above). */
1302 drag->drop_state.active_dropbox->draw_droptip(C, win, drag, xy);
1303 continue;
1304 }
1305 }
1306 else if (region) {
1307 CTX_wm_area_set(C, area);
1308 CTX_wm_region_set(C, region);
1309 }
1310
1311 /* Needs zero offset here or it looks blurry. #128112. */
1312 wmWindowViewport_ex(win, 0.0f);
1313 wm_drag_draw_default(C, win, drag, xy);
1314 }
1316 CTX_wm_area_set(C, nullptr);
1317 CTX_wm_region_set(C, nullptr);
1318 CTX_store_set(C, nullptr);
1319}
Main runtime representation of an asset.
void immDrawPixelsTexTiled_scaling(IMMDrawPixelsTexState *state, float x, float y, int img_w, int img_h, blender::gpu::TextureFormat gpu_format, bool use_filter, const void *rect, float scaleX, float scaleY, float xzoom, float yzoom, const float color[4])
Definition glutil.cc:309
IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin)
Definition glutil.cc:37
blender::Vector< PointerRNA > CTX_data_collection_get(const bContext *C, const char *member)
bScreen * CTX_wm_screen(const bContext *C)
SpaceFile * CTX_wm_space_file(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:1251
const char * BKE_idtype_idcode_to_name_plural(short idcode)
Definition idtype.cc:171
void BKE_id_free_us(Main *bmain, void *idv) ATTR_NONNULL()
void id_us_plus(ID *id)
Definition lib_id.cc:358
ARegion * BKE_area_find_region_xy(const ScrArea *area, int regiontype, const int xy[2]) ATTR_NONNULL(3)
Definition screen.cc:875
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:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_freelinkN(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:270
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:252
void void BLI_INLINE bool BLI_listbase_is_single(const ListBase *lb)
MINLINE int round_fl_to_int(float a)
MINLINE void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
#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_PACK
@ BLO_LIBLINK_APPEND_LOCAL_ID_REUSE
@ BLO_LIBLINK_COLLECTION_INSTANCE
#define TIP_(msgid)
ID_Type
eAssetImportMethod
@ ASSET_IMPORT_PACK
@ ASSET_IMPORT_LINK
@ ASSET_IMPORT_APPEND_REUSE
@ ASSET_IMPORT_APPEND
#define RGN_TYPE_ANY
#define RGN_TYPE_NUM
#define SPACE_TYPE_NUM
@ FILE_ACTIVE_COLLECTION
@ FILE_RELPATH
@ FILE_AUTOSELECT
#define SPACE_TYPE_ANY
struct AssetRepresentationHandle AssetRepresentationHandle
#define UI_SCALE_FAC
#define UI_INV_SCALE_FAC
#define UI_ICON_SIZE
#define KMAP_MAX_NAME
blender::Vector< std::string > ED_fileselect_selected_files_full_paths(const SpaceFile *sfile)
Definition filesel.cc:1489
int ED_path_extension_type(const char *path)
Definition filelist.cc:1786
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:296
void ED_region_tag_redraw_no_rebuild(ARegion *region)
Definition area.cc:638
@ 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(GPUBlend blend)
Definition gpu_state.cc:42
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define C
Definition RandGen.cpp:29
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)
void UI_icon_text_overlay_init_from_count(IconTextOverlay *text_overlay, const int icon_indicator_number)
#define UI_NO_ICON_OVERLAY_TEXT
#define PREVIEW_DRAG_DRAW_SIZE
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)
void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size)
@ TH_REDALERT
void UI_GetThemeColor4fv(int colorid, float col[4])
bTheme * UI_GetTheme()
std::string(*)(bContext *C, wmDrag *drag, const int xy[2], wmDropBox *drop) WMDropboxTooltipFunc
Definition WM_types.hh:1284
eWM_DragFlags
Definition WM_types.hh:1228
@ WM_DRAG_FREE_DATA
Definition WM_types.hh:1230
eWM_DragDataType
Definition WM_types.hh:1200
@ WM_DRAG_PATH
Definition WM_types.hh:1208
@ WM_DRAG_ASSET_LIST
Definition WM_types.hh:1206
@ WM_DRAG_GREASE_PENCIL_LAYER
Definition WM_types.hh:1221
@ WM_DRAG_STRING
Definition WM_types.hh:1217
@ WM_DRAG_ASSET_CATALOG
Definition WM_types.hh:1220
@ WM_DRAG_NAME
Definition WM_types.hh:1209
@ WM_DRAG_ASSET
Definition WM_types.hh:1202
@ WM_DRAG_ID
Definition WM_types.hh:1201
long long int int64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
int64_t size() const
void append(const T &value)
Span< T > as_span() const
constexpr const T * end() const
Definition BLI_span.hh:224
constexpr const T * begin() const
Definition BLI_span.hh:220
constexpr bool is_empty() const
Definition BLI_span.hh:260
constexpr bool is_empty() const
constexpr const char * c_str() const
void append(const T &value)
bool is_empty() const
#define str(s)
#define GS(x)
uint col
#define printf(...)
uint padding(uint offset, uint alignment)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static ulong state[N]
VecBase< int32_t, 2 > int2
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
const char * name
ARegionRuntimeHandle * runtime
eAssetImportMethod method
The meta-data of an asset. By creating and giving this for a data-block (ID.asset_data),...
Definition DNA_ID.h:414
struct AssetMetaData * asset_data
Definition DNA_ID.h:423
char name[258]
Definition DNA_ID.h:432
ImBufByteBuffer byte_buffer
void * first
ID * owner_id
Definition RNA_types.hh:51
StructRNA * type
Definition RNA_types.hh:52
void * data
Definition RNA_types.hh:53
ListBase handlers
uiWidgetColors wcol_tooltip
struct ARegion * active_region
ThemeUI tui
unsigned char inner[4]
unsigned char text[4]
const char * disabled_info
Definition WM_types.hh:1321
std::unique_ptr< bContextStore > ui_context
Definition WM_types.hh:1314
wmDropBox * active_dropbox
Definition WM_types.hh:1297
wmDragAsset * external_info
Definition WM_types.hh:1264
union wmDragAssetListItem::@356367110101130017201161164010115362272120017131 asset_data
const AssetRepresentationHandle * asset
Definition WM_types.hh:1243
AssetImportSettings import_settings
Definition WM_types.hh:1244
ID * from_parent
Definition WM_types.hh:1239
int file_types_bit_flag
Definition WM_types.hh:1275
blender::Vector< int > file_types
Definition WM_types.hh:1273
blender::Vector< std::string > paths
Definition WM_types.hh:1271
std::string tooltip
Definition WM_types.hh:1276
float imbuf_scale
Definition WM_types.hh:1336
eWM_DragDataType type
Definition WM_types.hh:1331
const ImBuf * imb
Definition WM_types.hh:1335
void * poin
Definition WM_types.hh:1332
int preview_icon_id
Definition WM_types.hh:1338
int icon
Definition WM_types.hh:1330
ListBase ids
Definition WM_types.hh:1345
ListBase asset_items
Definition WM_types.hh:1347
wmDragActiveDropState drop_state
Definition WM_types.hh:1340
eWM_DragFlags flags
Definition WM_types.hh:1342
ListBase dropboxes
char idname[KMAP_MAX_NAME]
wmDropBoxMap * prev
wmDropBoxMap * next
WMDropboxTooltipFunc tooltip
Definition WM_types.hh:1405
IDProperty * properties
Definition WM_types.hh:1418
void * draw_data
Definition WM_types.hh:1402
bool(* poll)(bContext *C, wmDrag *drag, const wmEvent *event)
Definition WM_types.hh:1363
void(* on_drag_start)(bContext *C, wmDrag *drag)
Definition WM_types.hh:1368
PointerRNA * ptr
Definition WM_types.hh:1420
wmOperatorType * ot
Definition WM_types.hh:1413
void(* on_exit)(wmDropBox *drop, wmDrag *drag)
Definition WM_types.hh:1375
void(* on_enter)(wmDropBox *drop, wmDrag *drag)
Definition WM_types.hh:1371
void(* cancel)(Main *bmain, wmDrag *drag, wmDropBox *drop)
Definition WM_types.hh:1384
char opname[64]
Definition WM_types.hh:1415
void(* draw_in_view)(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
Definition WM_types.hh:1399
void(* draw_droptip)(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
Definition WM_types.hh:1391
void(* copy)(bContext *C, wmDrag *drag, wmDropBox *drop)
Definition WM_types.hh:1378
short custom
Definition WM_types.hh:793
int xy[2]
Definition WM_types.hh:761
WindowManagerRuntimeHandle * runtime
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()
wmDragAsset * WM_drag_create_asset_data(const blender::asset_system::AssetRepresentation *asset, const AssetImportSettings &import_settings)
static void wm_drop_update_active(bContext *C, wmDrag *drag, const wmEvent *event)
static int wm_drag_preview_icon_size_get()
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)
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)
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)
Free asset ID imported for canceled drop.
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)
void WM_event_drag_path_override_poin_data_with_space_file_paths(const bContext *C, wmDrag *drag)
ID * WM_drag_get_local_ID_or_import_from_asset(const bContext *C, const wmDrag *drag, int idcode)
bool WM_drag_asset_will_import_packed(const wmDrag *drag)
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)
void WM_event_drag_preview_icon(wmDrag *drag, int icon_id)
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)
blender::wm::OpCallContext wm_drop_operator_context_get(const wmDropBox *)
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:178
bool WM_operator_poll_context(bContext *C, wmOperatorType *ot, blender::wm::OpCallContext context)
void WM_event_add_mousemove(wmWindow *win)
@ WM_HANDLER_TYPE_DROPBOX
@ EVT_DATA_DRAGDROP
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237
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:145