Fix: Incorrects filepaths on drag and drop with recursive option enabled

Currently drag and drop expects to selection to be in the same folder,
but blender internal file browser allows to select files from different
folders when recursion is active.

When writing to operator properties the `directory` is taken now from
the first file provided, and `files` are now relative to this
`directory` instead of just taking the file name.
When reading from operator properties filepaths are normalized.

I notice this issue while reading about #140942, the issue would
require a proper fix too.

Pull Request: https://projects.blender.org/blender/blender/pulls/140948
This commit is contained in:
Guillermo Venegas
2025-07-03 19:21:59 +02:00
committed by Julian Eisel
parent a9e6417e19
commit d441ac2d6f
5 changed files with 35 additions and 17 deletions

View File

@@ -8,6 +8,10 @@
#pragma once
#include <string>
#include "BLI_vector.hh"
#include "DNA_uuid_types.h"
struct ARegion;
@@ -203,6 +207,8 @@ ScrArea *ED_fileselect_handler_area_find_any_with_op(const wmWindow *win);
*/
void ED_fileselect_ensure_default_filepath(bContext *C, wmOperator *op, const char *extension);
blender::Vector<std::string> ED_fileselect_selected_files_full_paths(const SpaceFile *sfile);
/* TODO: Maybe we should move this to BLI?
* On the other hand, it's using defines from space-file area, so not sure... */
int ED_path_extension_type(const char *path);

View File

@@ -3,6 +3,7 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_path_utils.hh"
#include "BLI_string.h"
#include "BLT_translation.hh"
@@ -60,9 +61,9 @@ static void file_handler_import_operator_write_ptr(
}
PropertyRNA *directory_prop = RNA_struct_find_property_check(props, "directory", PROP_STRING);
char dir[FILE_MAX];
BLI_path_split_dir_part(paths[0].c_str(), dir, sizeof(dir));
if (directory_prop) {
char dir[FILE_MAX];
BLI_path_split_dir_part(paths[0].c_str(), dir, sizeof(dir));
RNA_property_string_set(&props, directory_prop, dir);
}
@@ -72,7 +73,8 @@ static void file_handler_import_operator_write_ptr(
RNA_property_collection_clear(&props, files_prop);
for (const auto &index : supported_paths) {
char file[FILE_MAX];
BLI_path_split_file_part(paths[index].c_str(), file, sizeof(file));
STRNCPY(file, paths[index].c_str());
BLI_path_rel(file, dir);
PointerRNA item_ptr{};
RNA_property_collection_add(&props, files_prop, &item_ptr);

View File

@@ -5,6 +5,7 @@
#include <fmt/format.h>
#include "BLI_path_utils.hh"
#include "BLI_string.h"
#include "BLT_translation.hh"
@@ -96,6 +97,7 @@ Vector<std::string> paths_from_operator_properties(PointerRNA *ptr)
RNA_string_get(&file_ptr, "name", name);
char path[FILE_MAX];
BLI_path_join(path, sizeof(path), directory, name);
BLI_path_normalize(path);
paths.append_non_duplicates(path);
}
RNA_PROP_END;
@@ -121,7 +123,8 @@ void paths_to_operator_properties(PointerRNA *ptr, const Span<std::string> paths
RNA_collection_clear(ptr, "files");
for (const auto &path : paths) {
char file[FILE_MAX];
BLI_path_split_file_part(path.c_str(), file, sizeof(file));
STRNCPY(file, path.c_str());
BLI_path_rel(file, dir);
PointerRNA itemptr{};
RNA_collection_add(ptr, "files", &itemptr);

View File

@@ -1502,3 +1502,17 @@ void ED_fileselect_ensure_default_filepath(bContext *C, wmOperator *op, const ch
RNA_string_set(op->ptr, "filepath", filepath);
}
}
blender::Vector<std::string> ED_fileselect_selected_files_full_paths(const SpaceFile *sfile)
{
blender::Vector<std::string> paths;
char path[FILE_MAX_LIBEXTRA];
for (const int i : blender::IndexRange(filelist_files_ensure(sfile->files))) {
if (filelist_entry_is_selected(sfile->files, i)) {
const FileDirEntry *entry = filelist_file(sfile->files, i);
filelist_file_get_full_path(sfile->files, entry, path);
paths.append(path);
}
}
return paths;
}

View File

@@ -21,7 +21,6 @@
#include "BLT_translation.hh"
#include "BLI_linear_allocator.hh"
#include "BLI_listbase.h"
#include "BLI_math_color.h"
#include "BLI_path_utils.hh"
@@ -365,21 +364,15 @@ void WM_event_drag_image(wmDrag *drag, const ImBuf *imb, float scale)
void WM_event_drag_path_override_poin_data_with_space_file_paths(const bContext *C, wmDrag *drag)
{
BLI_assert(drag->type == WM_DRAG_PATH);
if (!CTX_wm_space_file(C)) {
const SpaceFile *sfile = CTX_wm_space_file(C);
if (!sfile) {
return;
}
char dirpath[FILE_MAX];
BLI_path_split_dir_part(WM_drag_get_single_path(drag), dirpath, FILE_MAX);
blender::LinearAllocator<> allocator;
const blender::Vector<std::string> selected_paths = ED_fileselect_selected_files_full_paths(
sfile);
blender::Vector<const char *> paths;
const blender::Vector<PointerRNA> files = CTX_data_collection_get(C, "selected_files");
for (const PointerRNA &file_ptr : files) {
const FileDirEntry *file = static_cast<const FileDirEntry *>(file_ptr.data);
char filepath[FILE_MAX];
BLI_path_join(filepath, sizeof(filepath), dirpath, file->name);
paths.append(allocator.copy_string(filepath).c_str());
for (const std::string &path : selected_paths) {
paths.append(path.c_str());
}
if (paths.is_empty()) {
return;