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;
|
||||
}
|
||||
|
||||
|
|
|
@ -5944,7 +5944,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_single_path(drag));
|
||||
}
|
||||
|
||||
void ED_keymap_screen(wmKeyConfig *keyconf)
|
||||
|
|
|
@ -536,7 +536,7 @@ 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_single_path(drag), 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_single_path(drag));
|
||||
RNA_string_set(drop->ptr, "text", pathname);
|
||||
}
|
||||
|
||||
|
|
|
@ -797,7 +797,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_single_path(drag));
|
||||
}
|
||||
|
||||
/* 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_single_path(drag));
|
||||
}
|
||||
|
||||
/* area+region dropbox definition */
|
||||
|
|
|
@ -897,7 +897,7 @@ static void node_id_path_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
|
|||
return;
|
||||
}
|
||||
|
||||
const char *path = WM_drag_get_path(drag);
|
||||
const char *path = WM_drag_get_single_path(drag);
|
||||
if (path) {
|
||||
RNA_string_set(drop->ptr, "filepath", path);
|
||||
RNA_struct_property_unset(drop->ptr, "name");
|
||||
|
|
|
@ -249,7 +249,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_single_path(drag);
|
||||
/* Path dropped. */
|
||||
if (path) {
|
||||
if (RNA_struct_find_property(drop->ptr, "filepath")) {
|
||||
|
@ -335,7 +335,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_single_path(drag), FILE_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -316,7 +316,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_single_path(drag));
|
||||
}
|
||||
|
||||
static bool text_drop_paste_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
|
||||
|
|
|
@ -893,7 +893,7 @@ 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);
|
||||
const char *path = WM_drag_get_single_path(drag);
|
||||
if (path) {
|
||||
RNA_string_set(drop->ptr, "filepath", path);
|
||||
RNA_struct_property_unset(drop->ptr, "image");
|
||||
|
|
|
@ -210,3 +210,11 @@ blender_add_lib_nolist(bf_windowmanager "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
|||
|
||||
# RNA_prototypes.h
|
||||
add_dependencies(bf_windowmanager bf_rna)
|
||||
|
||||
if(WITH_GTESTS)
|
||||
set(TEST_SRC
|
||||
intern/wm_dragdrop_test.cc
|
||||
)
|
||||
include(GTestTesting)
|
||||
blender_add_test_lib(bf_wm_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB}")
|
||||
endif()
|
||||
|
|
|
@ -1424,16 +1424,32 @@ 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.
|
||||
guishe marked this conversation as resolved
Outdated
|
||||
*/
|
||||
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);
|
||||
/* If #drag contains path data, returns the first path int he path list. */
|
||||
guishe marked this conversation as resolved
Outdated
Julian Eisel
commented
The "For internal use only" part doesn't make sense to me, this is a public API. The "For internal use only" part doesn't make sense to me, this is a public API.
|
||||
const char *WM_drag_get_single_path(const wmDrag *drag);
|
||||
/* If #drag contains path data, returns the first path in the path list that maches a
|
||||
* a `file_type`.*/
|
||||
/*
|
||||
* \param drag: The drag that could contain drag path data.
|
||||
* \param file_type: `eFileSel_File_Types` bit flag
|
||||
*/
|
||||
const char *WM_drag_get_single_path(const wmDrag *drag, int file_type);
|
||||
blender::Span<std::string> WM_drag_get_paths(const wmDrag *drag);
|
||||
/* If #drag contains path data, returns if any file path match a `file_type`.*/
|
||||
/*
|
||||
* \param drag: The drag that could contain drag path data.
|
||||
* \param file_type: `eFileSel_File_Types` bit flag
|
||||
*/
|
||||
bool WM_drag_has_path_file_type(const wmDrag *drag, int file_type);
|
||||
/**
|
||||
* 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.
|
||||
* type-bits set, so `ELEM()` like comparison is possible. To check all paths or to do a bit-flag
|
||||
* check use `WM_drag_has_path_file_type(drag,file_type)` instead.
|
||||
*/
|
||||
int /* eFileSel_File_Types */ WM_drag_get_path_file_type(const wmDrag *drag);
|
||||
|
||||
|
|
|
@ -111,6 +111,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"
|
||||
|
@ -1179,10 +1180,12 @@ struct wmDragAssetListItem {
|
|||
};
|
||||
|
||||
struct wmDragPath {
|
||||
char *path;
|
||||
/* 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 */
|
||||
blender::Vector<std::string> paths;
|
||||
/* File type of each path in #paths. */
|
||||
blender::Vector<int> file_types; /* eFileSel_File_Types */
|
||||
/* Bit flag of file types in #paths. */
|
||||
int file_types_bit_flag; /* eFileSel_File_Types */
|
||||
std::string tooltip;
|
||||
};
|
||||
|
||||
struct wmDragGreasePencilLayer {
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "wm_event_system.h"
|
||||
#include "wm_window.hh"
|
||||
|
||||
#include <fmt/format.h>
|
||||
/* ****************************************************** */
|
||||
|
||||
static ListBase dropboxes = {nullptr, nullptr};
|
||||
|
@ -762,29 +763,80 @@ 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)
|
||||
{
|
||||
BLI_assert(!paths.is_empty());
|
||||
brecht marked this conversation as resolved
Outdated
Bastien Montagne
commented
Is there a reason for using string extension instead of the (already computed) 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. Is there a reason for using string extension instead of the (already computed) `file_type` here (and then comparing to the result of `ED_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.
Brecht Van Lommel
commented
`ED_path_extension_type` is only for file types that Blender natively supports, while this system is meant to work for arbitrary add-ons.
Guillermo Venegas
commented
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.
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 this `file_type` will just you describe the first path.
Bastien Montagne
commented
Ah yes, makes sense, better not do any filtering here then indeed. Ah yes, makes sense, better not do any filtering here then indeed.
|
||||
wmDragPath *path_data = MEM_new<wmDragPath>("wmDragPath");
|
||||
path_data->path = BLI_strdup(path);
|
||||
path_data->file_type = ED_path_extension_type(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.
|
||||
for (const char *path : paths) {
|
||||
path_data->paths.append(path);
|
||||
path_data->file_types_bit_flag |= ED_path_extension_type(path);
|
||||
path_data->file_types.append(ED_path_extension_type(path));
|
||||
}
|
||||
|
||||
path_data->tooltip = path_data->paths[0];
|
||||
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"`
|
||||
|
||||
if (path_data->paths.size() > 1) {
|
||||
std::string path_count = std::to_string(path_data->paths.size());
|
||||
path_data->tooltip = fmt::format(TIP_("Dragging {} files"), path_count);
|
||||
}
|
||||
|
||||
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 char *WM_drag_get_single_path(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 path_data->paths[0].c_str();
|
||||
guishe marked this conversation as resolved
Outdated
Julian Eisel
commented
Same, remove Same, remove `const` from return type.
|
||||
}
|
||||
|
||||
const char *WM_drag_get_single_path(const wmDrag *drag, int file_type)
|
||||
guishe marked this conversation as resolved
Outdated
Bastien Montagne
commented
`return nullptr;`
|
||||
{
|
||||
if (drag->type != WM_DRAG_PATH) {
|
||||
return nullptr;
|
||||
}
|
||||
const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
|
||||
auto const file_types = path_data->file_types;
|
||||
|
||||
auto itr = std::find_if(
|
||||
file_types.begin(), file_types.end(), [file_type](const int file_fype_test) {
|
||||
return file_fype_test & file_type;
|
||||
});
|
||||
|
||||
if (itr == file_types.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
const int index = itr - file_types.begin();
|
||||
return path_data->paths[index].c_str();
|
||||
}
|
||||
|
||||
bool WM_drag_has_path_file_type(const wmDrag *drag, int file_type)
|
||||
{
|
||||
if (drag->type != WM_DRAG_PATH) {
|
||||
return false;
|
||||
}
|
||||
const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
|
||||
return bool(path_data->file_types_bit_flag & file_type);
|
||||
}
|
||||
|
||||
blender::Span<std::string> WM_drag_get_paths(const wmDrag *drag)
|
||||
{
|
||||
if (drag->type != WM_DRAG_PATH) {
|
||||
return blender::Span<std::string>();
|
||||
}
|
||||
|
||||
const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
|
||||
return path_data->paths.as_span();
|
||||
}
|
||||
|
||||
int WM_drag_get_path_file_type(const wmDrag *drag)
|
||||
|
@ -794,7 +846,7 @@ int WM_drag_get_path_file_type(const wmDrag *drag)
|
|||
}
|
||||
|
||||
const wmDragPath *path_data = static_cast<const wmDragPath *>(drag->poin);
|
||||
return path_data->file_type;
|
||||
return path_data->file_types[0];
|
||||
}
|
||||
|
||||
/* ************** draw ***************** */
|
||||
|
@ -848,7 +900,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);
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "testing/testing.h"
|
||||
|
||||
/* #eFileSel_File_Types. */
|
||||
#include "DNA_space_types.h"
|
||||
brecht marked this conversation as resolved
Julian Eisel
commented
Doesn't seem to be needed. Doesn't seem to be needed.
Guillermo Venegas
commented
Needed by Needed by `wmDrag.drop_state.ui_context`, is a `std::unique_ptr<bContextStore>`
Julian Eisel
commented
While not a big deal, this include shouldn't be necessary. Committed While not a big deal, this include shouldn't be necessary. Committed e3b3399bcb so this can be removed now.
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
namespace blender::tests {
|
||||
|
||||
TEST(wm_drag, wmDragPath)
|
||||
{
|
||||
{
|
||||
/**
|
||||
guishe marked this conversation as resolved
Outdated
Julian Eisel
commented
Should mention that this is testing for paths specifically. Suggest something like Should mention that this is testing for paths specifically. Suggest something like `TEST(wm_drag, wmDragPath)`.
|
||||
* NOTE: `WM_drag_create_path_data` gets the `file_type` from the first path in `paths` and
|
||||
* only needs its extension, so there is no need to describe a full path here that can have a
|
||||
* different format on Windows or Linux. However callers must ensure that they are valid paths.
|
||||
*/
|
||||
blender::Vector<const char *> paths{"text_file.txt"};
|
||||
wmDragPath *path_data = WM_drag_create_path_data(paths);
|
||||
blender::Vector<std::string> expected_file_paths{"text_file.txt"};
|
||||
|
||||
EXPECT_EQ(path_data->paths.size(), 1);
|
||||
EXPECT_EQ(path_data->tooltip, "text_file.txt");
|
||||
EXPECT_EQ(path_data->paths, expected_file_paths);
|
||||
|
||||
/** Test `wmDrag` path data getters. */
|
||||
wmDrag drag;
|
||||
drag.type = WM_DRAG_PATH;
|
||||
drag.poin = path_data;
|
||||
EXPECT_STREQ(WM_drag_get_single_path(&drag), "text_file.txt");
|
||||
EXPECT_EQ(WM_drag_get_path_file_type(&drag), FILE_TYPE_TEXT);
|
||||
EXPECT_EQ(WM_drag_get_paths(&drag), expected_file_paths.as_span());
|
||||
EXPECT_STREQ(WM_drag_get_single_path(&drag, FILE_TYPE_TEXT), "text_file.txt");
|
||||
EXPECT_EQ(WM_drag_get_single_path(&drag, FILE_TYPE_BLENDER), nullptr);
|
||||
EXPECT_TRUE(
|
||||
WM_drag_has_path_file_type(&drag, FILE_TYPE_BLENDER | FILE_TYPE_TEXT | FILE_TYPE_IMAGE));
|
||||
EXPECT_FALSE(WM_drag_has_path_file_type(&drag, FILE_TYPE_BLENDER | FILE_TYPE_IMAGE));
|
||||
MEM_delete(path_data);
|
||||
}
|
||||
{
|
||||
blender::Vector<const char *> paths = {"blender.blend", "text_file.txt", "image.png"};
|
||||
wmDragPath *path_data = WM_drag_create_path_data(paths);
|
||||
blender::Vector<std::string> expected_file_paths = {
|
||||
"blender.blend", "text_file.txt", "image.png"};
|
||||
|
||||
EXPECT_EQ(path_data->paths.size(), 3);
|
||||
EXPECT_EQ(path_data->tooltip, "Dragging 3 files");
|
||||
EXPECT_EQ(path_data->paths, expected_file_paths);
|
||||
|
||||
/** Test `wmDrag` path data getters. */
|
||||
wmDrag drag;
|
||||
drag.type = WM_DRAG_PATH;
|
||||
drag.poin = path_data;
|
||||
EXPECT_STREQ(WM_drag_get_single_path(&drag), "blender.blend");
|
||||
EXPECT_EQ(WM_drag_get_path_file_type(&drag), FILE_TYPE_BLENDER);
|
||||
EXPECT_EQ(WM_drag_get_paths(&drag), expected_file_paths.as_span());
|
||||
EXPECT_STREQ(WM_drag_get_single_path(&drag, FILE_TYPE_BLENDER), "blender.blend");
|
||||
EXPECT_STREQ(WM_drag_get_single_path(&drag, FILE_TYPE_IMAGE), "image.png");
|
||||
EXPECT_STREQ(WM_drag_get_single_path(&drag, FILE_TYPE_TEXT), "text_file.txt");
|
||||
EXPECT_STREQ(
|
||||
WM_drag_get_single_path(&drag, FILE_TYPE_BLENDER | FILE_TYPE_TEXT | FILE_TYPE_IMAGE),
|
||||
"blender.blend");
|
||||
EXPECT_STREQ(WM_drag_get_single_path(&drag, FILE_TYPE_TEXT | FILE_TYPE_IMAGE),
|
||||
"text_file.txt");
|
||||
EXPECT_EQ(WM_drag_get_single_path(&drag, FILE_TYPE_ASSET), nullptr);
|
||||
EXPECT_TRUE(
|
||||
WM_drag_has_path_file_type(&drag, FILE_TYPE_BLENDER | FILE_TYPE_TEXT | FILE_TYPE_IMAGE));
|
||||
EXPECT_TRUE(WM_drag_has_path_file_type(&drag, FILE_TYPE_BLENDER | FILE_TYPE_IMAGE));
|
||||
EXPECT_TRUE(WM_drag_has_path_file_type(&drag, FILE_TYPE_IMAGE));
|
||||
EXPECT_FALSE(WM_drag_has_path_file_type(&drag, FILE_TYPE_ASSET));
|
||||
MEM_delete(path_data);
|
||||
}
|
||||
{
|
||||
/** Test `wmDrag` path data getters when the drag type is different to `WM_DRAG_PATH`. */
|
||||
wmDrag drag;
|
||||
drag.type = WM_DRAG_COLOR;
|
||||
EXPECT_EQ(WM_drag_get_single_path(&drag), nullptr);
|
||||
EXPECT_EQ(WM_drag_get_path_file_type(&drag), 0);
|
||||
EXPECT_EQ(WM_drag_get_paths(&drag).size(), 0);
|
||||
EXPECT_EQ(WM_drag_get_single_path(
|
||||
&drag, FILE_TYPE_BLENDER | FILE_TYPE_IMAGE | FILE_TYPE_TEXT | FILE_TYPE_ASSET),
|
||||
nullptr);
|
||||
EXPECT_FALSE(WM_drag_has_path_file_type(
|
||||
&drag, FILE_TYPE_BLENDER | FILE_TYPE_IMAGE | FILE_TYPE_TEXT | FILE_TYPE_ASSET));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::tests
|
|
@ -15,6 +15,8 @@
|
|||
#include <cstring>
|
||||
#include <thread>
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
|
@ -1649,14 +1651,17 @@ static bool ghost_event_proc(GHOST_EventHandle ghost_event, GHOST_TUserDataPtr C
|
|||
if (ddd->dataType == GHOST_kDragnDropTypeFilenames) {
|
||||
const GHOST_TStringArray *stra = static_cast<const GHOST_TStringArray *>(ddd->data);
|
||||
|
||||
for (int a = 0; a < stra->count; a++) {
|
||||
printf("drop file %s\n", stra->strings[a]);
|
||||
/* 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]);
|
||||
if (stra->count) {
|
||||
CLOG_INFO(WM_LOG_EVENTS, 1, "Drop %d files:", stra->count);
|
||||
for (const char *path : blender::Span((char **)stra->strings, stra->count)) {
|
||||
CLOG_INFO(WM_LOG_EVENTS, 1, "%s", path);
|
||||
}
|
||||
/* Try to get icon type from extension of the first path. */
|
||||
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 pointer should point to string, it makes a copy. */
|
||||
break; /* only one drop element supported now */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
This is returned by value, so
const
for the return type doesn't make sense (some static analyzers will warn I think).