IO: Add support for multiple drag-n-drop files #107230
|
@ -64,7 +64,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(blender::Span(&path, 1));
|
||||
but->dragflag |= UI_BUT_DRAGPOIN_FREE;
|
||||
}
|
||||
|
||||
|
|
|
@ -5907,7 +5907,7 @@ static bool blend_file_drop_poll(bContext * /*C*/, wmDrag *drag, const wmEvent *
|
|||
static void blend_file_drop_copy(bContext * /*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].c_str());
|
||||
}
|
||||
|
||||
void ED_keymap_screen(wmKeyConfig *keyconf)
|
||||
|
|
|
@ -536,7 +536,8 @@ static void clip_drop_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *drop)
|
|||
PointerRNA itemptr;
|
||||
char dir[FILE_MAX], file[FILE_MAX];
|
||||
|
||||
BLI_path_split_dir_file(WM_drag_get_path(drag), dir, sizeof(dir), file, sizeof(file));
|
||||
BLI_path_split_dir_file(
|
||||
WM_drag_get_paths(drag)[0].c_str(), dir, sizeof(dir), file, sizeof(file));
|
||||
|
||||
RNA_string_set(drop->ptr, "directory", dir);
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ static bool path_drop_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*eve
|
|||
static void path_drop_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *drop)
|
||||
{
|
||||
char pathname[FILE_MAX + 2];
|
||||
SNPRINTF(pathname, "\"%s\"", WM_drag_get_path(drag));
|
||||
SNPRINTF(pathname, "\"%s\"", WM_drag_get_paths(drag)[0].c_str());
|
||||
RNA_string_set(drop->ptr, "text", pathname);
|
||||
}
|
||||
|
||||
|
|
|
@ -799,7 +799,7 @@ static bool filepath_drop_poll(bContext *C, wmDrag *drag, const wmEvent * /*even
|
|||
|
||||
static void filepath_drop_copy(bContext * /*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].c_str());
|
||||
}
|
||||
|
||||
/* region dropbox definition */
|
||||
|
|
|
@ -268,7 +268,7 @@ static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
|
|||
static void image_drop_copy(bContext * /*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].c_str());
|
||||
}
|
||||
|
||||
/* area+region dropbox definition */
|
||||
|
|
|
@ -725,9 +725,9 @@ static void node_id_path_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
|
|||
return;
|
||||
}
|
||||
|
||||
const char *path = WM_drag_get_path(drag);
|
||||
if (path) {
|
||||
RNA_string_set(drop->ptr, "filepath", path);
|
||||
const auto paths = WM_drag_get_paths(drag);
|
||||
if (paths.begin()) {
|
||||
RNA_string_set(drop->ptr, "filepath", paths[0].c_str());
|
||||
RNA_struct_property_unset(drop->ptr, "name");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -249,17 +249,17 @@ static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
|
|||
return;
|
||||
}
|
||||
|
||||
const char *path = WM_drag_get_path(drag);
|
||||
const auto paths = WM_drag_get_paths(drag);
|
||||
/* Path dropped. */
|
||||
if (path) {
|
||||
if (paths.begin()) {
|
||||
if (RNA_struct_find_property(drop->ptr, "filepath")) {
|
||||
RNA_string_set(drop->ptr, "filepath", path);
|
||||
RNA_string_set(drop->ptr, "filepath", paths[0].c_str());
|
||||
}
|
||||
if (RNA_struct_find_property(drop->ptr, "directory")) {
|
||||
PointerRNA itemptr;
|
||||
char dir[FILE_MAX], file[FILE_MAX];
|
||||
|
||||
BLI_path_split_dir_file(path, dir, sizeof(dir), file, sizeof(file));
|
||||
BLI_path_split_dir_file(paths[0].c_str(), dir, sizeof(dir), file, sizeof(file));
|
||||
|
||||
RNA_string_set(drop->ptr, "directory", dir);
|
||||
|
||||
|
@ -337,7 +337,7 @@ static void get_drag_path(const bContext *C, 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].c_str(), FILE_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -315,7 +315,7 @@ static bool text_drop_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*eve
|
|||
static void text_drop_copy(bContext * /*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].c_str());
|
||||
}
|
||||
|
||||
static bool text_drop_paste_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
|
||||
|
|
|
@ -927,9 +927,9 @@ static void view3d_id_path_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
|
|||
RNA_struct_property_unset(drop->ptr, "filepath");
|
||||
return;
|
||||
}
|
||||
const char *path = WM_drag_get_path(drag);
|
||||
if (path) {
|
||||
RNA_string_set(drop->ptr, "filepath", path);
|
||||
const auto paths = WM_drag_get_paths(drag);
|
||||
if (paths.begin()) {
|
||||
RNA_string_set(drop->ptr, "filepath", paths[0].c_str());
|
||||
RNA_struct_property_unset(drop->ptr, "image");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1393,13 +1393,13 @@ const ListBase *WM_drag_asset_list_get(const wmDrag *drag);
|
|||
|
||||
const char *WM_drag_get_item_name(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. Values 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.
|
||||
*/
|
||||
wmDragPath *WM_drag_create_path_data(const char *path);
|
||||
const char *WM_drag_get_path(const wmDrag *drag);
|
||||
wmDragPath *WM_drag_create_path_data(blender::Span<const char *> paths);
|
||||
const blender::Span<std::string> WM_drag_get_paths(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.
|
||||
|
|
|
@ -106,6 +106,7 @@ struct wmWindowManager;
|
|||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_vector.hh"
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_uuid_types.h"
|
||||
#include "DNA_vec_types.h"
|
||||
|
@ -1125,10 +1126,15 @@ struct wmDragAssetListItem {
|
|||
};
|
||||
|
||||
struct wmDragPath {
|
||||
char *path;
|
||||
const blender::Vector<std::string> paths;
|
||||
/* 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 */
|
||||
const int file_type; /* eFileSel_File_Types */
|
||||
const std::string tooltip;
|
||||
wmDragPath(const blender::Vector<std::string> &paths, const std::string &tooltip, int file_type)
|
||||
: paths(std::move(paths)), file_type(file_type), tooltip(tooltip)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct wmDragGreasePencilLayer {
|
||||
|
|
|
@ -760,29 +760,45 @@ 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(blender::Span<const char *> _paths)
|
||||
{
|
||||
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]);
|
||||
blender::Vector<std::string> paths;
|
||||
for (auto path : _paths) {
|
||||
if (STREQ(ext, BLI_path_extension(path))) {
|
||||
brecht marked this conversation as resolved
Outdated
|
||||
paths.append(path);
|
||||
}
|
||||
guishe marked this conversation as resolved
Outdated
Julian Eisel
commented
This is just This is just `const char*` isn't it? In that case `auto` just hides type information with no real benefit, prefer not using it in such cases.
|
||||
}
|
||||
char *tooltip;
|
||||
if (_paths.size() == 1) {
|
||||
tooltip = BLI_strdup(_paths[0]);
|
||||
}
|
||||
else {
|
||||
tooltip = BLI_sprintfN(TIP_("Dragging %d %s files."), paths.size());
|
||||
guishe marked this conversation as resolved
Outdated
Bastien Montagne
commented
There is no reason to use C-strings here. There is no reason to use C-strings here. `std::string` and `fmt::format` (extern library we are using since we are not yet on C++20) should be even easier to use.
Bastien Montagne
commented
No final point in our UI strings: No final point in our UI strings: `"Dragging {} files"`
|
||||
}
|
||||
|
||||
wmDragPath *path_data = MEM_new<wmDragPath>(
|
||||
"wmDragPath", paths, tooltip, ED_path_extension_type(_paths[0]));
|
||||
|
||||
MEM_freeN(tooltip);
|
||||
|
||||
return path_data;
|
||||
}
|
||||
|
||||
static void wm_drag_free_path_data(wmDragPath **path_data)
|
||||
{
|
||||
MEM_freeN((*path_data)->path);
|
||||
MEM_delete(*path_data);
|
||||
*path_data = nullptr;
|
||||
}
|
||||
|
||||
const char *WM_drag_get_path(const wmDrag *drag)
|
||||
const blender::Span<std::string> WM_drag_get_paths(const wmDrag *drag)
|
||||
{
|
||||
if (drag->type != WM_DRAG_PATH) {
|
||||
return nullptr;
|
||||
return blender::Span<std::string>();
|
||||
}
|
||||
|
||||
const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
|
||||
guishe marked this conversation as resolved
Outdated
Julian Eisel
commented
Same, remove Same, remove `const` from return type.
|
||||
return path_data->path;
|
||||
return path_data->paths.as_span();
|
||||
}
|
||||
|
||||
guishe marked this conversation as resolved
Outdated
Bastien Montagne
commented
`return nullptr;`
|
||||
int WM_drag_get_path_file_type(const wmDrag *drag)
|
||||
|
@ -846,7 +862,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.c_str();
|
||||
}
|
||||
case WM_DRAG_NAME:
|
||||
return static_cast<const char *>(drag->poin);
|
||||
|
@ -1039,8 +1055,9 @@ void wm_drags_draw(bContext *C, wmWindow *win)
|
|||
wmWindowViewport(win);
|
||||
}
|
||||
|
||||
/* Drawing should be allowed to assume the context from handling and polling (that's why we
|
||||
* restore it above). */
|
||||
/* Drawing should be allowed to assume the context from
|
||||
* handling and polling (that's why we restore it
|
||||
* above). */
|
||||
if (drag->drop_state.active_dropbox->draw_droptip) {
|
||||
drag->drop_state.active_dropbox->draw_droptip(C, win, drag, xy);
|
||||
continue;
|
||||
|
|
|
@ -1512,14 +1512,14 @@ wm_window_swap_buffers(win);
|
|||
if (ddd->dataType == GHOST_kDragnDropTypeFilenames) {
|
||||
GHOST_TStringArray *stra = static_cast<GHOST_TStringArray *>(ddd->data);
|
||||
|
||||
for (int a = 0; a < stra->count; a++) {
|
||||
printf("drop file %s\n", stra->strings[a]);
|
||||
if (stra->count) {
|
||||
printf("drop file %s\n", stra->strings[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(
|
||||
blender::Span((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 */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Is there a reason for using string extension instead of the (already computed)
file_type
here (and then comparing to the result ofED_path_extension_type
for all other paths in the loop below)?If yes, should be documented in a comment.
Current approach would also 'fail' (filter out valid paths) e.g. in case of paths to a mix of JPG and PNG images. Or paths containing several USD files with different extensions.
ED_path_extension_type
is only for file types that Blender natively supports, while this system is meant to work for arbitrary add-ons.Initially I had the idea of just the one extension for file handler, but since file handlers could have a list of files they can take, here we can copy all and then see which ones are useful for the file handlers.
path_data->file_type
would only be used internally with the first file, and since these changes don't change the behavior I think it's safe to keep it and collect all the file paths, I'll leave a note that thisfile_type
will just you describe the first path.Ah yes, makes sense, better not do any filtering here then indeed.