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
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->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->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->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_append_datablock(bmain,
758 scene,
759 view_layer,
760 view3d,
761 blend_path.c_str(),
762 idtype,
763 name,
768 G_MAIN,
769 scene,
770 view_layer,
771 view3d,
772 blend_path.c_str(),
773 idtype,
774 name,
776 BLO_LIBLINK_APPEND_LOCAL_ID_REUSE | (use_relative_path ? FILE_RELPATH : 0));
777 }
778
780 return nullptr;
781}
782
784{
785 if (drag->type != WM_DRAG_ASSET) {
786 return false;
787 }
788
789 const wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0);
790 return asset_drag->import_settings.method == ASSET_IMPORT_LINK;
791}
792
794{
795 if (!ELEM(drag->type, WM_DRAG_ASSET, WM_DRAG_ID)) {
796 return nullptr;
797 }
798
799 if (drag->type == WM_DRAG_ID) {
800 return WM_drag_get_local_ID(drag, idcode);
801 }
802
803 wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, idcode);
804 if (!asset_drag) {
805 return nullptr;
806 }
807
808 /* Link/append the asset. */
809 return WM_drag_asset_id_import(C, asset_drag, 0);
810}
811
813{
814 if (drag->type != WM_DRAG_ASSET) {
815 return;
816 }
817
818 wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0);
819 if (!asset_drag) {
820 return;
821 }
822
823 ID_Type asset_id_type = asset_drag->asset->get_id_type();
824 /* Try to find the imported ID. For this to work either a "session_uid" or "name" property must
825 * have been defined (see #WM_operator_properties_id_lookup()). */
827 bmain, drop->ptr, asset_id_type);
828 if (id != nullptr) {
829 /* Do not delete the dragged ID if it has any user, otherwise if it is a 're-used' ID it will
830 * cause #95636. Note that we need first to add the user that we want to remove in
831 * #BKE_id_free_us. */
832 id_us_plus(id);
833 BKE_id_free_us(bmain, id);
834 }
835}
836
838{
839 if (drag->type != WM_DRAG_ASSET_CATALOG) {
840 return nullptr;
841 }
842
843 return static_cast<wmDragAssetCatalog *>(drag->poin);
844}
845
848{
850
851 /* No guarantee that the same asset isn't added twice. */
852
853 /* Add to list. */
855 ID *local_id = asset->local_id();
856 if (local_id) {
857 drag_asset->is_external = false;
858 drag_asset->asset_data.local_id = local_id;
859 }
860 else {
861 drag_asset->is_external = true;
862
863 AssetImportSettings import_settings{};
864 import_settings.method = ASSET_IMPORT_APPEND;
865 import_settings.use_instance_collections = false;
866
867 drag_asset->asset_data.external_info = WM_drag_create_asset_data(asset, import_settings);
868 }
869 BLI_addtail(&drag->asset_items, drag_asset);
870}
871
873{
874 if (drag->type != WM_DRAG_ASSET_LIST) {
875 return nullptr;
876 }
877
878 return &drag->asset_items;
879}
880
882{
883 BLI_assert(!paths.is_empty());
884 wmDragPath *path_data = MEM_new<wmDragPath>("wmDragPath");
885
886 for (const char *path : paths) {
887 path_data->paths.append(path);
888 const int type_flag = ED_path_extension_type(path);
889 path_data->file_types_bit_flag |= type_flag;
890 path_data->file_types.append(type_flag);
891 }
892
893 path_data->tooltip = path_data->paths[0];
894
895 if (path_data->paths.size() > 1) {
896 std::string path_count = std::to_string(path_data->paths.size());
897 path_data->tooltip = fmt::format(fmt::runtime(TIP_("Dragging {} files")), path_count);
898 }
899
900 return path_data;
901}
902
903static void wm_drag_free_path_data(wmDragPath **path_data)
904{
905 MEM_delete(*path_data);
906 *path_data = nullptr;
907}
908
909const char *WM_drag_get_single_path(const wmDrag *drag)
910{
911 if (drag->type != WM_DRAG_PATH) {
912 return nullptr;
913 }
914
915 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
916 return path_data->paths[0].c_str();
917}
918
919const char *WM_drag_get_single_path(const wmDrag *drag, int file_type)
920{
921 if (drag->type != WM_DRAG_PATH) {
922 return nullptr;
923 }
924 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
925 const blender::Span<int> file_types = path_data->file_types;
926
927 const auto *itr = std::find_if(
928 file_types.begin(), file_types.end(), [file_type](const int file_fype_test) {
929 return file_fype_test & file_type;
930 });
931
932 if (itr == file_types.end()) {
933 return nullptr;
934 }
935 const int index = itr - file_types.begin();
936 return path_data->paths[index].c_str();
937}
938
939bool WM_drag_has_path_file_type(const wmDrag *drag, int file_type)
940{
941 if (drag->type != WM_DRAG_PATH) {
942 return false;
943 }
944 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
945 return bool(path_data->file_types_bit_flag & file_type);
946}
947
949{
950 if (drag->type != WM_DRAG_PATH) {
952 }
953
954 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
955 return path_data->paths.as_span();
956}
957
959{
960 if (drag->type != WM_DRAG_PATH) {
961 return 0;
962 }
963
964 const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
965 return path_data->file_types[0];
966}
967
968const std::string &WM_drag_get_string(const wmDrag *drag)
969{
971 const std::string *str = static_cast<const std::string *>(drag->poin);
972 return *str;
973}
974
975std::string WM_drag_get_string_firstline(const wmDrag *drag)
976{
978 const std::string *str = static_cast<const std::string *>(drag->poin);
979 const size_t str_eol = str->find('\n');
980 if (str_eol != std::string::npos) {
981 return str->substr(0, str_eol);
982 }
983 return *str;
984}
985
986/* ************** draw ***************** */
987
988static void wm_drop_operator_draw(const blender::StringRef name, int x, int y)
989{
990 const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
991
992 /* Use the theme settings from tooltips. */
993 const bTheme *btheme = UI_GetTheme();
994 const uiWidgetColors *wcol = &btheme->tui.wcol_tooltip;
995
996 float col_fg[4], col_bg[4];
997 rgba_uchar_to_float(col_fg, wcol->text);
998 rgba_uchar_to_float(col_bg, wcol->inner);
999
1000 UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg);
1001}
1002
1003static void wm_drop_redalert_draw(const blender::StringRef redalert_str, int x, int y)
1004{
1005 const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
1006 const bTheme *btheme = UI_GetTheme();
1007 const uiWidgetColors *wcol = &btheme->tui.wcol_tooltip;
1008
1009 float col_fg[4], col_bg[4];
1011 rgba_uchar_to_float(col_bg, wcol->inner);
1012
1013 UI_fontstyle_draw_simple_backdrop(fstyle, x, y, redalert_str, col_fg, col_bg);
1014}
1015
1017{
1018 switch (drag->type) {
1019 case WM_DRAG_ID: {
1020 ID *id = WM_drag_get_local_ID(drag, 0);
1021 bool single = BLI_listbase_is_single(&drag->ids);
1022
1023 if (single) {
1024 return id->name + 2;
1025 }
1026 if (id) {
1028 }
1029 break;
1030 }
1031 case WM_DRAG_ASSET: {
1032 const wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0);
1033 return asset_drag->asset->get_name().c_str();
1034 }
1035 case WM_DRAG_PATH: {
1036 const wmDragPath *path_drag_data = static_cast<const wmDragPath *>(drag->poin);
1037 return path_drag_data->tooltip.c_str();
1038 }
1039 case WM_DRAG_NAME:
1040 return static_cast<const char *>(drag->poin);
1041 default:
1042 break;
1043 }
1044 return "";
1045}
1046
1048{
1049 return round_fl_to_int(drag->imb->x * drag->imbuf_scale);
1050}
1051
1053{
1054 return round_fl_to_int(drag->imb->y * drag->imbuf_scale);
1055}
1056
1058{
1060}
1061
1062static void wm_drag_draw_icon(bContext * /*C*/, wmWindow * /*win*/, wmDrag *drag, const int xy[2])
1063{
1064 int x, y;
1065
1066 if (const int64_t path_count = WM_drag_get_paths(drag).size(); path_count > 1) {
1067 /* Custom scale to improve path count readability. */
1068 const float scale = UI_SCALE_FAC * 1.15f;
1069 x = xy[0] - int(8.0f * scale);
1070 y = xy[1] - int(scale);
1071 const uchar text_col[] = {255, 255, 255, 255};
1072 IconTextOverlay text_overlay;
1073 UI_icon_text_overlay_init_from_count(&text_overlay, path_count);
1075 x, y, ICON_DOCUMENTS, 1.0f / scale, 1.0f, 0.0f, text_col, false, &text_overlay);
1076 }
1077 else if (drag->imb) {
1078 /* This could also get the preview image of an ID when dragging one. But the big preview icon
1079 * may actually not always be wanted, for example when dragging objects in the Outliner it gets
1080 * in the way). So make the drag user set an image buffer explicitly (e.g. through
1081 * #UI_but_drag_attach_image()). */
1082
1083 x = xy[0] - (wm_drag_imbuf_icon_width_get(drag) / 2);
1084 y = xy[1] - (wm_drag_imbuf_icon_height_get(drag) / 2);
1085
1086 const float col[4] = {1.0f, 1.0f, 1.0f, 0.65f}; /* This blends texture. */
1089 x,
1090 y,
1091 drag->imb->x,
1092 drag->imb->y,
1093 GPU_RGBA8,
1094 false,
1095 drag->imb->byte_buffer.data,
1096 drag->imbuf_scale,
1097 drag->imbuf_scale,
1098 1.0f,
1099 1.0f,
1100 col);
1101 }
1102 else if (drag->preview_icon_id) {
1103 const int size = wm_drag_preview_icon_size_get();
1104 x = xy[0] - (size / 2);
1105 y = xy[1] - (size / 2);
1106
1107 UI_icon_draw_preview(x, y, drag->preview_icon_id, 1.0, 0.8, size);
1108 }
1109 else {
1110 int padding = 4 * UI_SCALE_FAC;
1111 x = xy[0] - 2 * padding;
1112 y = xy[1] - 2 * UI_SCALE_FAC;
1113
1114 const uchar text_col[] = {255, 255, 255, 255};
1116 x, y, drag->icon, UI_INV_SCALE_FAC, 0.8, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT);
1117 }
1118}
1119
1120static void wm_drag_draw_item_name(wmDrag *drag, const int x, const int y)
1121{
1122 const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
1123 const uchar text_col[] = {255, 255, 255, 255};
1124 UI_fontstyle_draw_simple(fstyle, x, y, WM_drag_get_item_name(drag), text_col);
1125}
1126
1127void WM_drag_draw_item_name_fn(bContext * /*C*/, wmWindow *win, wmDrag *drag, const int xy[2])
1128{
1129 int x = xy[0] + 10 * UI_SCALE_FAC;
1130 int y = xy[1] + 1 * UI_SCALE_FAC;
1131
1132 /* Needs zero offset here or it looks blurry. #128112. */
1133 wmWindowViewport_ex(win, 0.0f);
1134 wm_drag_draw_item_name(drag, x, y);
1135}
1136
1137static void wm_drag_draw_tooltip(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
1138{
1139 if (!CTX_wm_region(C)) {
1140 /* Some callbacks require the region. */
1141 return;
1142 }
1143 int iconsize = UI_ICON_SIZE;
1144 int padding = 4 * UI_SCALE_FAC;
1145 blender::StringRef tooltip = drag->drop_state.tooltip;
1146 const bool has_disabled_info = drag->drop_state.disabled_info &&
1147 drag->drop_state.disabled_info[0];
1148 if (tooltip.is_empty() && !has_disabled_info) {
1149 return;
1150 }
1151
1152 const int winsize_y = WM_window_native_pixel_y(win);
1153 int x, y;
1154 if (drag->imb) {
1155 const int icon_width = wm_drag_imbuf_icon_width_get(drag);
1156 const int icon_height = wm_drag_imbuf_icon_height_get(drag);
1157
1158 x = xy[0] - (icon_width / 2);
1159
1160 if (xy[1] + (icon_height / 2) + padding + iconsize < winsize_y) {
1161 y = xy[1] + (icon_height / 2) + padding;
1162 }
1163 else {
1164 y = xy[1] - (icon_height / 2) - padding - iconsize - padding - iconsize;
1165 }
1166 }
1167 if (WM_drag_get_paths(drag).size() > 1) {
1168 x = xy[0] - 2 * padding;
1169
1170 if (xy[1] + 2 * 1.15 * iconsize < winsize_y) {
1171 y = xy[1] + 1.15f * (iconsize + 6 * UI_SCALE_FAC);
1172 }
1173 else {
1174 y = xy[1] - 1.15f * (iconsize + padding);
1175 }
1176 }
1177 else if (drag->preview_icon_id) {
1178 const int size = wm_drag_preview_icon_size_get();
1179
1180 x = xy[0] - (size / 2);
1181
1182 if (xy[1] + (size / 2) + padding + iconsize < winsize_y) {
1183 y = xy[1] + (size / 2) + padding;
1184 }
1185 else {
1186 y = xy[1] - (size / 2) - padding - iconsize - padding - iconsize;
1187 }
1188 }
1189 else {
1190 x = xy[0] - 2 * padding;
1191
1192 if (xy[1] + iconsize + iconsize < winsize_y) {
1193 y = (xy[1] + iconsize) + padding;
1194 }
1195 else {
1196 y = (xy[1] - iconsize) - padding;
1197 }
1198 }
1199
1200 if (!tooltip.is_empty()) {
1201 wm_drop_operator_draw(tooltip, x, y);
1202 }
1203 else if (has_disabled_info) {
1205 }
1206}
1207
1208static void wm_drag_draw_default(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
1209{
1210 int xy_tmp[2] = {UNPACK2(xy)};
1211
1212 /* Image or icon. */
1213 wm_drag_draw_icon(C, win, drag, xy_tmp);
1214
1215 /* Item name. */
1216 if (drag->imb) {
1217 int iconsize = UI_ICON_SIZE;
1218 xy_tmp[0] = xy[0] - (wm_drag_imbuf_icon_width_get(drag) / 2);
1219 xy_tmp[1] = xy[1] - (wm_drag_imbuf_icon_height_get(drag) / 2) - iconsize;
1220 }
1221 else if (drag->preview_icon_id) {
1222 const int icon_size = UI_ICON_SIZE;
1223 const int preview_size = wm_drag_preview_icon_size_get();
1224 xy_tmp[0] = xy[0] - (preview_size / 2);
1225 xy_tmp[1] = xy[1] - (preview_size / 2) - icon_size;
1226 }
1227 else {
1228 xy_tmp[0] = xy[0] + 10 * UI_SCALE_FAC;
1229 xy_tmp[1] = xy[1] + 1 * UI_SCALE_FAC;
1230 }
1231 if (WM_drag_get_paths(drag).size() < 2) {
1232 wm_drag_draw_item_name(drag, UNPACK2(xy_tmp));
1233 }
1234
1235 /* Operator name with round-box. */
1236 wm_drag_draw_tooltip(C, win, drag, xy);
1237}
1238
1239void WM_drag_draw_default_fn(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
1240{
1241 wm_drag_draw_default(C, win, drag, xy);
1242}
1243
1245{
1246 const int *xy = win->eventstate->xy;
1247
1248 int xy_buf[2];
1250 wm_cursor_position_get(win, &xy_buf[0], &xy_buf[1]))
1251 {
1252 xy = xy_buf;
1253 }
1254
1255 bScreen *screen = CTX_wm_screen(C);
1256 /* To start with, use the area and region under the mouse cursor, just like event handling. The
1257 * operator context may still override it. */
1260 /* Will be overridden and unset eventually. */
1262
1264
1265 /* Should we support multi-line drag draws? Maybe not, more types mixed won't work well. */
1267 LISTBASE_FOREACH (wmDrag *, drag, &wm->drags) {
1268 if (drag->drop_state.active_dropbox) {
1271 CTX_store_set(C, drag->drop_state.ui_context.get());
1272
1273 if (region && drag->drop_state.active_dropbox->draw_in_view) {
1274 wmViewport(&region->winrct);
1275 drag->drop_state.active_dropbox->draw_in_view(C, win, drag, xy);
1276 wmWindowViewport(win);
1277 }
1278
1279 /* Drawing should be allowed to assume the context from handling and polling (that's why we
1280 * restore it above). */
1282 drag->drop_state.active_dropbox->draw_droptip(C, win, drag, xy);
1283 continue;
1284 }
1285 }
1286 else if (region) {
1287 CTX_wm_area_set(C, area);
1288 CTX_wm_region_set(C, region);
1289 }
1290
1291 /* Needs zero offset here or it looks blurry. #128112. */
1292 wmWindowViewport_ex(win, 0.0f);
1293 wm_drag_draw_default(C, win, drag, xy);
1294 }
1296 CTX_wm_area_set(C, nullptr);
1297 CTX_wm_region_set(C, nullptr);
1298 CTX_store_set(C, nullptr);
1299}
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])
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
blender::Vector< std::string > ED_fileselect_selected_files_full_paths(const SpaceFile *sfile)
Definition filesel.cc:1509
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()
std::string(*)(bContext *C, wmDrag *drag, const int xy[2], wmDropBox *drop) WMDropboxTooltipFunc
Definition WM_types.hh:1280
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
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)
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),...
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::@233164355256014341113315010302145064113230043040 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:4227
wmOperatorType * ot
Definition wm_files.cc:4226
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