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