WIP: UI: Add Drag & Drop Feedback on Windows #107056

Draft
Guillermo Venegas wants to merge 3 commits from guishe/blender:drag-and-drop-update into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
16 changed files with 86 additions and 39 deletions
Showing only changes of commit 2650becbb7 - Show all commits

View File

@ -70,7 +70,7 @@ void UI_but_drag_set_path(uiBut *but, const char *path)
if (but->dragflag & UI_BUT_DRAGPOIN_FREE) {
WM_drag_data_free(but->dragtype, but->dragpoin);
}
but->dragpoin = WM_drag_create_path_data(path);
but->dragpoin = WM_drag_create_path_data(&path, 1);
but->dragflag |= UI_BUT_DRAGPOIN_FREE;
}

View File

@ -535,7 +535,7 @@ bool obj_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED
if (drag->type == WM_DRAG_PATH) {
const eFileSel_File_Types file_type = WM_drag_get_path_file_type(drag);
if (file_type == FILE_TYPE_OBJECT_IO &&
BLI_path_extension_check(WM_drag_get_path(drag), ".obj")) {
BLI_path_extension_check(WM_drag_get_paths(drag)[0], ".obj")) {
return true;
}
}

View File

@ -55,24 +55,27 @@ void skip_save_import_paths_props(wmOperatorType *ot, const eFileSel_Flag flag)
void files_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
const char **paths = WM_drag_get_paths(drag);
RNA_string_set(drop->ptr, "filepath", paths[0]);
RNA_string_set(drop->ptr, "filepath", WM_drag_get_path(drag));
// TODO(@guishe): Add support for multiple drag&drop files import
char dir[FILE_MAX], file[FILE_MAX];
BLI_split_dirfile(WM_drag_get_path(drag), dir, file, sizeof(dir), sizeof(file));
BLI_split_dirfile(paths[0], dir, file, sizeof(dir), sizeof(file));
RNA_string_set(drop->ptr, "directory", dir);
RNA_collection_clear(drop->ptr, "files");
PointerRNA itemptr;
RNA_collection_add(drop->ptr, "files", &itemptr);
RNA_string_set(&itemptr, "name", file);
const int path_count = WM_drag_get_path_count(drag);
for (int i = 0; i < path_count; i++) {
BLI_split_dirfile(paths[i], dir, file, sizeof(dir), sizeof(file));
PointerRNA itemptr;
RNA_collection_add(drop->ptr, "files", &itemptr);
RNA_string_set(&itemptr, "name", file);
}
}
void file_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
RNA_string_set(drop->ptr, "filepath", WM_drag_get_path(drag));
RNA_string_set(drop->ptr, "filepath", WM_drag_get_paths(drag)[0]);
}
void file_drop_info_draw(bContext *C, wmOperator *op, int icon)

View File

@ -4564,7 +4564,7 @@ static void screen_animation_region_tag_redraw(
ED_region_tag_redraw(region);
}
//#define PROFILE_AUDIO_SYNCH
// #define PROFILE_AUDIO_SYNCH
static int screen_animation_step_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
@ -5756,7 +5756,7 @@ static bool blend_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEven
static void blend_file_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
/* copy drag path to properties */
RNA_string_set(drop->ptr, "filepath", WM_drag_get_path(drag));
RNA_string_set(drop->ptr, "filepath", WM_drag_get_paths(drag)[0]);
}
void ED_keymap_screen(wmKeyConfig *keyconf)

View File

@ -527,7 +527,7 @@ static void clip_drop_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *drop)
PointerRNA itemptr;
char dir[FILE_MAX], file[FILE_MAX];
BLI_split_dirfile(WM_drag_get_path(drag), dir, file, sizeof(dir), sizeof(file));
BLI_split_dirfile(WM_drag_get_paths(drag)[0], dir, file, sizeof(dir), sizeof(file));
RNA_string_set(drop->ptr, "directory", dir);

View File

@ -172,7 +172,7 @@ static bool path_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNU
static void path_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
char pathname[FILE_MAX + 2];
BLI_snprintf(pathname, sizeof(pathname), "\"%s\"", WM_drag_get_path(drag));
BLI_snprintf(pathname, sizeof(pathname), "\"%s\"", WM_drag_get_paths(drag)[0]);
RNA_string_set(drop->ptr, "text", pathname);
}

View File

@ -783,7 +783,7 @@ static bool filepath_drop_poll(bContext *C, wmDrag *drag, const wmEvent *UNUSED(
static void filepath_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
RNA_string_set(drop->ptr, "filepath", WM_drag_get_path(drag));
RNA_string_set(drop->ptr, "filepath", WM_drag_get_paths(drag)[0]);
}
/* region dropbox definition */

View File

@ -268,7 +268,7 @@ static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
static void image_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
/* copy drag path to properties */
RNA_string_set(drop->ptr, "filepath", WM_drag_get_path(drag));
RNA_string_set(drop->ptr, "filepath", WM_drag_get_paths(drag)[0]);
}
/* area+region dropbox definition */

View File

@ -711,7 +711,7 @@ static void node_id_path_drop_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *dr
return;
}
const char *path = WM_drag_get_path(drag);
const char *path = WM_drag_get_paths(drag)[0];
if (path) {
RNA_string_set(drop->ptr, "filepath", path);
RNA_struct_property_unset(drop->ptr, "name");

View File

@ -247,7 +247,7 @@ static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
return;
}
const char *path = WM_drag_get_path(drag);
const char *path = WM_drag_get_paths(drag)[0];
/* Path dropped. */
if (path) {
if (RNA_struct_find_property(drop->ptr, "filepath")) {
@ -335,7 +335,7 @@ static void get_drag_path(wmDrag *drag, char r_path[FILE_MAX])
BLI_path_abs(r_path, BKE_main_blendfile_path_from_global());
}
else {
BLI_strncpy(r_path, WM_drag_get_path(drag), FILE_MAX);
BLI_strncpy(r_path, WM_drag_get_paths(drag)[0], FILE_MAX);
}
}

View File

@ -312,7 +312,7 @@ static bool text_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNU
static void text_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
/* copy drag path to properties */
RNA_string_set(drop->ptr, "filepath", WM_drag_get_path(drag));
RNA_string_set(drop->ptr, "filepath", WM_drag_get_paths(drag)[0]);
}
static bool text_drop_paste_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))

View File

@ -903,7 +903,7 @@ static void view3d_id_path_drop_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *
RNA_struct_property_unset(drop->ptr, "filepath");
return;
}
const char *path = WM_drag_get_path(drag);
const char *path = WM_drag_get_paths(drag)[0];
if (path) {
RNA_string_set(drop->ptr, "filepath", path);
RNA_struct_property_unset(drop->ptr, "image");

View File

@ -1445,13 +1445,15 @@ const ListBase *WM_drag_asset_list_get(const wmDrag *drag);
const char *WM_drag_get_item_name(struct wmDrag *drag);
/* Path drag and drop. */
/* Paths drag and drop. */
/**
* \param path: The path to drag. Value will be copied into the drag data so the passed string may
* be destructed.
* \param paths: The paths to drag. Value will be copied into the drag data so the passed strings
* may be destructed. Only paths that share the same extension of the first file will be copied.
* \param path_count: the number of paths in #paths
*/
wmDragPath *WM_drag_create_path_data(const char *path);
const char *WM_drag_get_path(const wmDrag *drag);
wmDragPath *WM_drag_create_path_data(const char **paths, int path_count);
const char **WM_drag_get_paths(const wmDrag *drag);
const int WM_drag_get_path_count(const wmDrag *drag);
/**
* Note that even though the enum return type uses bit-flags, this should never have multiple
* type-bits set, so `ELEM()` like comparison is possible.

View File

@ -1133,7 +1133,9 @@ typedef struct wmDragAssetListItem {
} wmDragAssetListItem;
typedef struct wmDragPath {
char *path;
char **paths;
char *tooltip;
int path_count;
/* Note that even though the enum type uses bit-flags, this should never have multiple type-bits
* set, so `ELEM()` like comparison is possible. */
int file_type; /* eFileSel_File_Types */

View File

@ -750,29 +750,70 @@ const ListBase *WM_drag_asset_list_get(const wmDrag *drag)
return &drag->asset_items;
}
wmDragPath *WM_drag_create_path_data(const char *path)
wmDragPath *WM_drag_create_path_data(const char **paths, int path_count)
{
wmDragPath *path_data = MEM_new<wmDragPath>("wmDragPath");
path_data->path = BLI_strdup(path);
path_data->file_type = ED_path_extension_type(path);
const char *ext = BLI_path_extension(paths[0]);
int valid_path_count = 1;
for (int i = 1; i < path_count; i++) {
if ((ext == nullptr && BLI_path_extension(paths[i]) == nullptr) ||
(ext != nullptr && BLI_path_extension_check(paths[i], ext))) {
valid_path_count++;
}
}
path_data->paths = (char **)MEM_mallocN(valid_path_count * sizeof(char *), "paths");
int path_index = 0;
for (int i = 0; i < path_count; i++) {
if ((ext == nullptr && BLI_path_extension(paths[i]) == nullptr) ||
(ext != nullptr && BLI_path_extension_check(paths[i], ext))) {
path_data->paths[path_index] = BLI_strdup(paths[i]);
path_index++;
}
}
path_data->file_type = ED_path_extension_type(paths[0]);
path_data->path_count = valid_path_count;
if (path_count == 1) {
path_data->tooltip = BLI_strdup(paths[0]);
}
else {
const char *tooltip = TIP_("Dragging %d %s files.");
path_data->tooltip = BLI_sprintfN(tooltip, valid_path_count, ext);
}
return path_data;
}
static void wm_drag_free_path_data(wmDragPath **path_data)
{
MEM_freeN((*path_data)->path);
for (int i = 0; i < (*path_data)->path_count; i++) {
MEM_freeN((*path_data)->paths[i]);
}
MEM_freeN((*path_data)->paths);
MEM_freeN((*path_data)->tooltip);
MEM_delete(*path_data);
*path_data = nullptr;
}
const char *WM_drag_get_path(const wmDrag *drag)
const char **WM_drag_get_paths(const wmDrag *drag)
{
if (drag->type != WM_DRAG_PATH) {
return nullptr;
}
const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
return path_data->path;
return const_cast<const char **>(path_data->paths);
}
const int WM_drag_get_path_count(const wmDrag *drag)
{
if (drag->type != WM_DRAG_PATH) {
return 0;
}
const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
return path_data->path_count;
}
int WM_drag_get_path_file_type(const wmDrag *drag)
@ -836,7 +877,7 @@ const char *WM_drag_get_item_name(wmDrag *drag)
}
case WM_DRAG_PATH: {
const wmDragPath *path_drag_data = static_cast<const wmDragPath *>(drag->poin);
return path_drag_data->path;
return path_drag_data->tooltip;
}
case WM_DRAG_NAME:
return static_cast<const char *>(drag->poin);

View File

@ -1487,11 +1487,10 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_pt
if (ddd->dataType == GHOST_kDragnDropTypeFilenames) {
GHOST_TStringArray *stra = ddd->data;
for (int a = 0; a < stra->count; a++) {
printf("drop file %s\n", stra->strings[a]);
if (stra->count > 0) {
/* try to get icon type from extension */
int icon = ED_file_extension_icon((char *)stra->strings[a]);
wmDragPath *path_data = WM_drag_create_path_data((char *)stra->strings[a]);
int icon = ED_file_extension_icon((char *)stra->strings[0]);
wmDragPath *path_data = WM_drag_create_path_data((char **)stra->strings, stra->count);
WM_event_start_drag(C, icon, WM_DRAG_PATH, path_data, 0.0, WM_DRAG_NOP);
/* void poin should point to string, it makes a copy */
break; /* only one drop element supported now */