WIP: Experiment: Drop import operator helper and file drop type #111242
|
@ -3494,6 +3494,76 @@ class WM_OT_drop_blend_file(Operator):
|
|||
col.operator("wm.append", text="Append...", icon='APPEND_BLEND').filepath = self.filepath
|
||||
|
||||
|
||||
class WM_FDT_alembic(bpy.types.FileDrop):
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_idname = "WM_FDT_alembic"
|
||||
bl_operator = "WM_OT_alembic_import"
|
||||
|
||||
@classmethod
|
||||
def poll_extension(cls, context, extension):
|
||||
return extension == ".abc"
|
||||
|
||||
|
||||
class WM_FDT_collada(bpy.types.FileDrop):
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_idname = "WM_FDT_collada"
|
||||
bl_operator = "WM_OT_collada_import"
|
||||
|
||||
@classmethod
|
||||
def poll_extension(cls, context, extension):
|
||||
return extension == ".dae"
|
||||
|
||||
|
||||
class WM_FDT_gpencil(bpy.types.FileDrop):
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_idname = "WM_FDT_gpencil"
|
||||
bl_operator = "WM_OT_gpencil_import_svg"
|
||||
|
||||
@classmethod
|
||||
def poll_extension(cls, context, extension):
|
||||
return extension == ".svg"
|
||||
|
||||
|
||||
class WM_FDT_obj(bpy.types.FileDrop):
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_idname = "WM_FDT_obj"
|
||||
bl_operator = "WM_OT_obj_import"
|
||||
|
||||
@classmethod
|
||||
def poll_extension(cls, context, extension):
|
||||
return extension == ".obj"
|
||||
|
||||
|
||||
class WM_FDT_ply(bpy.types.FileDrop):
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_idname = "WM_FDT_ply"
|
||||
bl_operator = "WM_OT_ply_import"
|
||||
|
||||
@classmethod
|
||||
def poll_extension(cls, context, extension):
|
||||
return extension == ".ply"
|
||||
|
||||
|
||||
class WM_FDT_stl(bpy.types.FileDrop):
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_idname = "WM_FDT_stl"
|
||||
bl_operator = "WM_OT_stl_import"
|
||||
|
||||
@classmethod
|
||||
def poll_extension(cls, context, extension):
|
||||
return extension == ".stl"
|
||||
|
||||
|
||||
class WM_FDT_usd(bpy.types.FileDrop):
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_idname = "WM_FDT_usd"
|
||||
bl_operator = "WM_OT_usd_import"
|
||||
|
||||
@classmethod
|
||||
def poll_extension(cls, context, extension):
|
||||
return extension == ".usd"
|
||||
|
||||
|
||||
classes = (
|
||||
WM_OT_context_collection_boolean_set,
|
||||
WM_OT_context_cycle_array,
|
||||
|
@ -3539,5 +3609,13 @@ classes = (
|
|||
WM_MT_splash_quick_setup,
|
||||
WM_MT_splash,
|
||||
WM_MT_splash_about,
|
||||
WM_MT_region_toggle_pie
|
||||
WM_MT_region_toggle_pie,
|
||||
|
||||
WM_FDT_alembic,
|
||||
WM_FDT_collada,
|
||||
WM_FDT_gpencil,
|
||||
WM_FDT_obj,
|
||||
WM_FDT_ply,
|
||||
WM_FDT_stl,
|
||||
WM_FDT_usd,
|
||||
)
|
||||
|
|
|
@ -139,6 +139,9 @@ typedef struct SpaceType {
|
|||
/** Asset shelf type definitions. */
|
||||
ListBase asset_shelf_types; /* #AssetShelfType */
|
||||
|
||||
/** File drop type definitions. */
|
||||
ListBase file_drop_types; /* #FileDropType */
|
||||
|
||||
/* read and write... */
|
||||
|
||||
/** Default key-maps to add. */
|
||||
|
@ -461,6 +464,28 @@ typedef struct AssetShelfType {
|
|||
ExtensionRNA rna_ext;
|
||||
} AssetShelfType;
|
||||
|
||||
typedef struct FileDropType {
|
||||
struct FileDropType *next, *prev;
|
||||
|
||||
char idname[BKE_ST_MAXNAME]; /* unique name */
|
||||
|
||||
char op_name[BKE_ST_MAXNAME]; /* operator name */
|
||||
|
||||
int space_type;
|
||||
|
||||
/** Determine if the operator can handle a specific file extension. */
|
||||
bool (*poll_extension)(const struct bContext *C,
|
||||
FileDropType *file_drop_type,
|
||||
const char *extension);
|
||||
|
||||
/* RNA integration */
|
||||
ExtensionRNA rna_ext;
|
||||
} FileDropType;
|
||||
|
||||
typedef struct FileDrop {
|
||||
struct FileDropType *type; /* runtime */
|
||||
} FileDrop;
|
||||
|
||||
/* Space-types. */
|
||||
|
||||
struct SpaceType *BKE_spacetype_from_id(int spaceid);
|
||||
|
|
|
@ -225,6 +225,7 @@ static void spacetype_free(SpaceType *st)
|
|||
|
||||
BLI_freelistN(&st->regiontypes);
|
||||
BLI_freelistN(&st->asset_shelf_types);
|
||||
BLI_freelistN(&st->file_drop_types);
|
||||
}
|
||||
|
||||
void BKE_spacetypes_free()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ set(SRC
|
|||
io_ply_ops.cc
|
||||
io_stl_ops.cc
|
||||
io_usd.cc
|
||||
io_utils.cc
|
||||
io_drop_import_helper.cc
|
||||
|
||||
io_alembic.hh
|
||||
io_cache.hh
|
||||
|
@ -46,6 +48,8 @@ set(SRC
|
|||
io_ply_ops.hh
|
||||
io_stl_ops.hh
|
||||
io_usd.hh
|
||||
io_utils.hh
|
||||
io_drop_import_helper.hh
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
|
|
@ -55,6 +55,8 @@
|
|||
|
||||
# include "ABC_alembic.h"
|
||||
|
||||
# include "io_utils.hh"
|
||||
|
||||
const EnumPropertyItem rna_enum_abc_export_evaluation_mode_items[] = {
|
||||
{DAG_EVAL_RENDER,
|
||||
"RENDER",
|
||||
|
@ -584,8 +586,9 @@ static void ui_alembic_import_settings(uiLayout *layout, PointerRNA *imfptr)
|
|||
uiItemR(col, imfptr, "always_add_cache_reader", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
}
|
||||
|
||||
static void wm_alembic_import_draw(bContext * /*C*/, wmOperator *op)
|
||||
static void wm_alembic_import_draw(bContext *C, wmOperator *op)
|
||||
{
|
||||
files_drop_label_draw(C, op, ICON_FILE_3D, ".abc");
|
||||
ui_alembic_import_settings(op->layout, op->ptr);
|
||||
}
|
||||
|
||||
|
@ -595,7 +598,7 @@ static int wm_alembic_import_invoke(bContext *C, wmOperator *op, const wmEvent *
|
|||
if (!RNA_struct_property_is_set(op->ptr, "as_background_job")) {
|
||||
RNA_boolean_set(op->ptr, "as_background_job", true);
|
||||
}
|
||||
return WM_operator_filesel(C, op, event);
|
||||
return wm_io_import_invoke(C, op, event);
|
||||
}
|
||||
|
||||
static int wm_alembic_import_exec(bContext *C, wmOperator *op)
|
||||
|
@ -651,7 +654,7 @@ void WM_OT_alembic_import(wmOperatorType *ot)
|
|||
ot->name = "Import Alembic";
|
||||
ot->description = "Load an Alembic archive";
|
||||
ot->idname = "WM_OT_alembic_import";
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_PRESET;
|
||||
ot->flag = OPTYPE_UNDO | OPTYPE_PRESET;
|
||||
|
||||
ot->invoke = wm_alembic_import_invoke;
|
||||
ot->exec = wm_alembic_import_exec;
|
||||
|
@ -665,6 +668,7 @@ void WM_OT_alembic_import(wmOperatorType *ot)
|
|||
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS,
|
||||
FILE_DEFAULTDISPLAY,
|
||||
FILE_SORT_DEFAULT);
|
||||
skip_filesel_props(ot, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH);
|
||||
|
||||
PropertyRNA *prop = RNA_def_string(ot->srna, "filter_glob", "*.abc", 0, "", "");
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
# include "ED_fileselect.hh"
|
||||
# include "ED_object.hh"
|
||||
# include "ED_outliner.hh"
|
||||
|
||||
# include "RNA_access.hh"
|
||||
# include "RNA_define.hh"
|
||||
|
@ -35,6 +36,7 @@
|
|||
# include "collada.h"
|
||||
|
||||
# include "io_collada.hh"
|
||||
# include "io_utils.hh"
|
||||
|
||||
static int wm_collada_export_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
||||
{
|
||||
|
@ -747,6 +749,11 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
|
|||
|
||||
if (collada_import(C, &import_settings)) {
|
||||
DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_BASE_FLAGS);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
|
||||
ED_outliner_select_sync_from_object_tag(C);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
@ -782,8 +789,9 @@ static void uiCollada_importSettings(uiLayout *layout, PointerRNA *imfptr)
|
|||
uiItemR(box, imfptr, "keep_bind_info", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
}
|
||||
|
||||
static void wm_collada_import_draw(bContext * /*C*/, wmOperator *op)
|
||||
static void wm_collada_import_draw(bContext *C, wmOperator *op)
|
||||
{
|
||||
files_drop_label_draw(C, op, ICON_FILE_3D, "dae");
|
||||
uiCollada_importSettings(op->layout, op->ptr);
|
||||
}
|
||||
|
||||
|
@ -792,9 +800,9 @@ void WM_OT_collada_import(wmOperatorType *ot)
|
|||
ot->name = "Import COLLADA";
|
||||
ot->description = "Load a Collada file";
|
||||
ot->idname = "WM_OT_collada_import";
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_PRESET;
|
||||
ot->flag = OPTYPE_UNDO | OPTYPE_PRESET;
|
||||
|
||||
ot->invoke = WM_operator_filesel;
|
||||
ot->invoke = wm_io_import_invoke;
|
||||
ot->exec = wm_collada_import_exec;
|
||||
ot->poll = WM_operator_winactive;
|
||||
|
||||
|
@ -807,6 +815,7 @@ void WM_OT_collada_import(wmOperatorType *ot)
|
|||
WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS,
|
||||
FILE_DEFAULTDISPLAY,
|
||||
FILE_SORT_DEFAULT);
|
||||
skip_filesel_props(ot, WM_FILESEL_FILEPATH);
|
||||
|
||||
PropertyRNA *prop = RNA_def_string(ot->srna, "filter_glob", "*.dae", 0, "", "");
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_preferences.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "ED_fileselect.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_define.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "io_drop_import_helper.hh"
|
||||
|
||||
static wmOperatorType *get_operator_type_for_extension(const bContext *C, const char *extension)
|
||||
{
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
SpaceType *st = area->type;
|
||||
|
||||
FileDropType *file_drop_type = nullptr;
|
||||
|
||||
LISTBASE_FOREACH (FileDropType *, file_drop_test, &st->file_drop_types) {
|
||||
if (file_drop_test->poll_extension &&
|
||||
file_drop_test->poll_extension(C, file_drop_test, extension)) {
|
||||
file_drop_type = file_drop_test;
|
||||
}
|
||||
};
|
||||
return file_drop_type ? WM_operatortype_find(file_drop_type->op_name, false) : nullptr;
|
||||
}
|
||||
|
||||
static int wm_drop_import_helper_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
char extension[MAX_NAME];
|
||||
RNA_string_get(op->ptr, "extension", extension);
|
||||
|
||||
wmOperatorType *ot = get_operator_type_for_extension(C, extension);
|
||||
|
||||
if (!ot) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
PointerRNA op_props;
|
||||
WM_operator_properties_create_ptr(&op_props, ot);
|
||||
|
||||
char filepath[FILE_MAX];
|
||||
if (RNA_struct_find_property(&op_props, "filepath")) {
|
||||
RNA_string_get(op->ptr, "filepath", filepath);
|
||||
RNA_string_set(&op_props, "filepath", filepath);
|
||||
}
|
||||
|
||||
if (RNA_struct_find_property(&op_props, "directory")) {
|
||||
RNA_string_get(op->ptr, "directory", filepath);
|
||||
RNA_string_set(&op_props, "directory", filepath);
|
||||
|
||||
RNA_collection_clear(&op_props, "files");
|
||||
int files_len = RNA_collection_length(op->ptr, "files");
|
||||
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "files");
|
||||
|
||||
for (int i = 0; i < files_len; i++) {
|
||||
PointerRNA fileptr;
|
||||
RNA_property_collection_lookup_int(op->ptr, prop, i, &fileptr);
|
||||
RNA_string_get(&fileptr, "name", filepath);
|
||||
|
||||
PointerRNA itemptr{};
|
||||
RNA_collection_add(&op_props, "files", &itemptr);
|
||||
RNA_string_set(&itemptr, "name", filepath);
|
||||
}
|
||||
}
|
||||
|
||||
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props, nullptr);
|
||||
WM_operator_properties_free(&op_props);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void WM_OT_drop_import_helper(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Drop Import Herlper";
|
||||
ot->description =
|
||||
"Helper operator that handles file drops events and calls operators that can import files "
|
||||
"with extension";
|
||||
ot->idname = "WM_OT_drop_import_helper";
|
||||
|
||||
ot->exec = wm_drop_import_helper_exec;
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_string(ot->srna, "extension", nullptr, MAX_NAME, "extension", "extension");
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||
|
||||
WM_operator_properties_filesel(ot,
|
||||
FILE_TYPE_FOLDER,
|
||||
FILE_BLENDER,
|
||||
FILE_OPENFILE,
|
||||
WM_FILESEL_FILEPATH | WM_FILESEL_FILES | WM_FILESEL_DIRECTORY |
|
||||
WM_FILESEL_SHOW_PROPS,
|
||||
FILE_DEFAULTDISPLAY,
|
||||
FILE_SORT_DEFAULT);
|
||||
}
|
||||
|
||||
void files_drop_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *drop)
|
||||
{
|
||||
const auto paths = WM_drag_get_paths(drag);
|
||||
RNA_string_set(drop->ptr, "filepath", paths[0].c_str());
|
||||
|
||||
char dir[FILE_MAX], file[FILE_MAX];
|
||||
RNA_string_set(drop->ptr, "extension", BLI_path_extension(paths[0].c_str()));
|
||||
|
||||
BLI_path_split_dir_file(paths[0].c_str(), dir, sizeof(dir), file, sizeof(file));
|
||||
RNA_string_set(drop->ptr, "directory", dir);
|
||||
|
||||
RNA_collection_clear(drop->ptr, "files");
|
||||
for (const auto &path : paths) {
|
||||
BLI_path_split_dir_file(path.c_str(), dir, sizeof(dir), file, sizeof(file));
|
||||
|
||||
PointerRNA itemptr{};
|
||||
RNA_collection_add(drop->ptr, "files", &itemptr);
|
||||
RNA_string_set(&itemptr, "name", file);
|
||||
}
|
||||
}
|
||||
|
||||
static bool poll(bContext *C, wmDrag *drag, const wmEvent * /*event*/)
|
||||
guishe marked this conversation as resolved
Outdated
|
||||
{
|
||||
if (drag->type != WM_DRAG_PATH) {
|
||||
return false;
|
||||
}
|
||||
const auto paths = WM_drag_get_paths(drag);
|
||||
const char *extension = BLI_path_extension(paths[0].c_str());
|
||||
|
||||
return extension && get_operator_type_for_extension(C, extension);
|
||||
}
|
||||
static char *tooltip(bContext *C, wmDrag *drag, const int /*xy*/[2], wmDropBox * /*drop*/)
|
||||
{
|
||||
const auto paths = WM_drag_get_paths(drag);
|
||||
const char *extension = BLI_path_extension(paths[0].c_str());
|
||||
|
||||
guishe marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
Leave empty line between function definitions. Leave empty line between function definitions.
|
||||
wmOperatorType *ot = get_operator_type_for_extension(C, extension);
|
||||
|
||||
if (!ot || (!ot->name || !ot->description)) {
|
||||
brecht marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
Herlper -> Helper But I would not put "helper" in the name, lots of operators are helpers in some way and it doesn't really explain much. Maybe "Drop to Import File"? Herlper -> Helper
But I would not put "helper" in the name, lots of operators are helpers in some way and it doesn't really explain much.
Maybe "Drop to Import File"?
|
||||
return nullptr;
|
||||
}
|
||||
return BLI_strdup(ot->name ? ot->name : ot->description);
|
||||
}
|
||||
guishe marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
Add Add `ot->flag = OPTYPE_INTERNAL;`, this does not need to appear in search.
|
||||
|
||||
void ED_dropbox_import_helper()
|
||||
{
|
||||
ListBase *lb = WM_dropboxmap_find("Window", 0, 0);
|
||||
WM_dropbox_add(lb, "WM_OT_drop_import_helper", poll, files_drop_copy, nullptr, tooltip);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
struct wmOperatorType;
|
||||
|
||||
void WM_OT_drop_import_helper(wmOperatorType *ot);
|
||||
void ED_dropbox_import_helper();
|
|
@ -36,6 +36,7 @@
|
|||
# include "ED_gpencil_legacy.hh"
|
||||
|
||||
# include "io_gpencil.hh"
|
||||
# include "io_utils.hh"
|
||||
|
||||
# include "gpencil_io.h"
|
||||
|
||||
|
@ -55,13 +56,6 @@ static bool wm_gpencil_import_svg_common_check(bContext * /*C*/, wmOperator *op)
|
|||
return false;
|
||||
}
|
||||
|
||||
static int wm_gpencil_import_svg_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
||||
{
|
||||
WM_event_add_fileselect(C, op);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int wm_gpencil_import_svg_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
@ -136,13 +130,15 @@ static void ui_gpencil_import_svg_settings(uiLayout *layout, PointerRNA *imfptr)
|
|||
{
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
uiLayoutSetPropDecorate(layout, false);
|
||||
uiLayout *col = uiLayoutColumn(layout, false);
|
||||
uiLayout *box = uiLayoutBox(layout);
|
||||
uiLayout *col = uiLayoutColumn(box, false);
|
||||
uiItemR(col, imfptr, "resolution", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
uiItemR(col, imfptr, "scale", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
}
|
||||
|
||||
static void wm_gpencil_import_svg_draw(bContext * /*C*/, wmOperator *op)
|
||||
static void wm_gpencil_import_svg_draw(bContext *C, wmOperator *op)
|
||||
{
|
||||
files_drop_label_draw(C, op, ICON_FILE_3D, ".svg");
|
||||
ui_gpencil_import_svg_settings(op->layout, op->ptr);
|
||||
}
|
||||
|
||||
|
@ -161,7 +157,7 @@ void WM_OT_gpencil_import_svg(wmOperatorType *ot)
|
|||
ot->description = "Import SVG into grease pencil";
|
||||
ot->idname = "WM_OT_gpencil_import_svg";
|
||||
|
||||
ot->invoke = wm_gpencil_import_svg_invoke;
|
||||
ot->invoke = wm_io_import_invoke;
|
||||
ot->exec = wm_gpencil_import_svg_exec;
|
||||
ot->poll = wm_gpencil_import_svg_poll;
|
||||
ot->ui = wm_gpencil_import_svg_draw;
|
||||
|
@ -175,6 +171,8 @@ void WM_OT_gpencil_import_svg(wmOperatorType *ot)
|
|||
WM_FILESEL_DIRECTORY | WM_FILESEL_FILES,
|
||||
FILE_DEFAULTDISPLAY,
|
||||
FILE_SORT_DEFAULT);
|
||||
skip_filesel_props(
|
||||
ot, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES);
|
||||
|
||||
RNA_def_int(ot->srna,
|
||||
"resolution",
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
# include "IO_wavefront_obj.h"
|
||||
|
||||
# include "io_obj.hh"
|
||||
# include "io_utils.hh"
|
||||
|
||||
static const EnumPropertyItem io_obj_export_evaluation_mode[] = {
|
||||
{DAG_EVAL_RENDER, "DAG_EVAL_RENDER", 0, "Render", "Export objects as they appear in render"},
|
||||
|
@ -386,12 +387,6 @@ void WM_OT_obj_export(wmOperatorType *ot)
|
|||
RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
}
|
||||
|
||||
static int wm_obj_import_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
||||
{
|
||||
WM_event_add_fileselect(C, op);
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int wm_obj_import_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
OBJImportParams import_params{};
|
||||
|
@ -473,6 +468,7 @@ static void wm_obj_import_draw(bContext *C, wmOperator *op)
|
|||
PointerRNA ptr;
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
|
||||
files_drop_label_draw(C, op, ICON_FILE_3D, ".obj");
|
||||
ui_obj_import_settings(op->layout, &ptr);
|
||||
}
|
||||
|
||||
|
@ -483,9 +479,9 @@ void WM_OT_obj_import(wmOperatorType *ot)
|
|||
ot->name = "Import Wavefront OBJ";
|
||||
ot->description = "Load a Wavefront OBJ scene";
|
||||
ot->idname = "WM_OT_obj_import";
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_PRESET;
|
||||
ot->flag = OPTYPE_UNDO | OPTYPE_PRESET;
|
||||
|
||||
ot->invoke = wm_obj_import_invoke;
|
||||
ot->invoke = wm_io_import_invoke;
|
||||
ot->exec = wm_obj_import_exec;
|
||||
ot->poll = WM_operator_winactive;
|
||||
ot->ui = wm_obj_import_draw;
|
||||
|
@ -499,6 +495,8 @@ void WM_OT_obj_import(wmOperatorType *ot)
|
|||
FILE_DEFAULTDISPLAY,
|
||||
FILE_SORT_DEFAULT);
|
||||
|
||||
skip_filesel_props(ot, WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES);
|
||||
|
||||
RNA_def_float(
|
||||
ot->srna,
|
||||
"global_scale",
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#endif
|
||||
|
||||
#include "io_cache.hh"
|
||||
#include "io_drop_import_helper.hh"
|
||||
#include "io_gpencil.hh"
|
||||
#include "io_obj.hh"
|
||||
#include "io_ply_ops.hh"
|
||||
|
@ -73,4 +74,6 @@ void ED_operatortypes_io()
|
|||
#ifdef WITH_IO_STL
|
||||
WM_operatortype_append(WM_OT_stl_import);
|
||||
#endif
|
||||
WM_operatortype_append(WM_OT_drop_import_helper);
|
||||
ED_dropbox_import_helper();
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
# include "IO_ply.h"
|
||||
# include "io_ply_ops.hh"
|
||||
# include "io_utils.hh"
|
||||
|
||||
static const EnumPropertyItem ply_vertex_colors_mode[] = {
|
||||
{PLY_VERTEX_COLOR_NONE, "NONE", 0, "None", "Do not import/export color attributes"},
|
||||
|
@ -231,11 +232,6 @@ void WM_OT_ply_export(wmOperatorType *ot)
|
|||
RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
}
|
||||
|
||||
static int wm_ply_import_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
return WM_operator_filesel(C, op, event);
|
||||
}
|
||||
|
||||
static int wm_ply_import_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
PLYImportParams params{};
|
||||
|
@ -280,6 +276,30 @@ static int wm_ply_import_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void ui_ply_import_settings(uiLayout *layout, PointerRNA *imfptr)
|
||||
{
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
uiLayoutSetPropDecorate(layout, false);
|
||||
|
||||
uiLayout *box = uiLayoutBox(layout);
|
||||
uiLayout *col = uiLayoutColumn(box, false);
|
||||
uiItemR(col, imfptr, "global_scale", UI_ITEM_NONE, NULL, ICON_NONE);
|
||||
uiItemR(col, imfptr, "use_scene_unit", UI_ITEM_NONE, NULL, ICON_NONE);
|
||||
uiItemR(col, imfptr, "forward_axis", UI_ITEM_NONE, IFACE_("Forward Axis"), ICON_NONE);
|
||||
uiItemR(col, imfptr, "up_axis", UI_ITEM_NONE, NULL, ICON_NONE);
|
||||
uiItemR(col, imfptr, "merge_verts", UI_ITEM_NONE, NULL, ICON_NONE);
|
||||
uiItemR(col, imfptr, "import_colors", UI_ITEM_NONE, NULL, ICON_NONE);
|
||||
}
|
||||
|
||||
static void wm_ply_import_draw(bContext *C, wmOperator *op)
|
||||
{
|
||||
PointerRNA ptr;
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
|
||||
files_drop_label_draw(C, op, ICON_FILE_3D, ".ply");
|
||||
ui_ply_import_settings(op->layout, &ptr);
|
||||
}
|
||||
|
||||
void WM_OT_ply_import(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
@ -288,10 +308,11 @@ void WM_OT_ply_import(wmOperatorType *ot)
|
|||
ot->description = "Import an PLY file as an object";
|
||||
ot->idname = "WM_OT_ply_import";
|
||||
|
||||
ot->invoke = wm_ply_import_invoke;
|
||||
ot->invoke = wm_io_import_invoke;
|
||||
ot->exec = wm_ply_import_exec;
|
||||
ot->poll = WM_operator_winactive;
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_PRESET;
|
||||
ot->ui = wm_ply_import_draw;
|
||||
ot->flag = OPTYPE_UNDO | OPTYPE_PRESET;
|
||||
|
||||
WM_operator_properties_filesel(ot,
|
||||
FILE_TYPE_FOLDER,
|
||||
|
@ -301,6 +322,7 @@ void WM_OT_ply_import(wmOperatorType *ot)
|
|||
WM_FILESEL_SHOW_PROPS,
|
||||
FILE_DEFAULTDISPLAY,
|
||||
FILE_SORT_DEFAULT);
|
||||
skip_filesel_props(ot, WM_FILESEL_FILEPATH | WM_FILESEL_FILES | WM_FILESEL_DIRECTORY);
|
||||
|
||||
RNA_def_float(ot->srna, "global_scale", 1.0f, 1e-6f, 1e6f, "Scale", "", 0.001f, 1000.0f);
|
||||
RNA_def_boolean(ot->srna,
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#ifdef WITH_IO_STL
|
||||
|
||||
# include "BLT_translation.h"
|
||||
|
||||
# include "BKE_context.h"
|
||||
# include "BKE_report.h"
|
||||
|
||||
|
@ -21,13 +23,12 @@
|
|||
# include "RNA_access.hh"
|
||||
# include "RNA_define.hh"
|
||||
|
||||
# include "UI_interface.hh"
|
||||
# include "UI_resources.hh"
|
||||
|
||||
# include "IO_stl.h"
|
||||
# include "io_stl_ops.hh"
|
||||
|
||||
static int wm_stl_import_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
return WM_operator_filesel(C, op, event);
|
||||
}
|
||||
# include "io_utils.hh"
|
||||
|
||||
static int wm_stl_import_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
|
@ -85,6 +86,29 @@ static bool wm_stl_import_check(bContext * /*C*/, wmOperator *op)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
static void ui_stl_import_settings(uiLayout *layout, PointerRNA *imfptr)
|
||||
{
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
uiLayoutSetPropDecorate(layout, false);
|
||||
|
||||
uiLayout *box = uiLayoutBox(layout);
|
||||
uiLayout *col = uiLayoutColumn(box, false);
|
||||
uiItemR(col, imfptr, "global_scale", UI_ITEM_NONE, NULL, ICON_NONE);
|
||||
uiItemR(col, imfptr, "use_scene_unit", UI_ITEM_NONE, NULL, ICON_NONE);
|
||||
uiItemR(col, imfptr, "use_facet_normal", UI_ITEM_NONE, NULL, ICON_NONE);
|
||||
uiItemR(col, imfptr, "forward_axis", UI_ITEM_NONE, IFACE_("Forward Axis"), ICON_NONE);
|
||||
uiItemR(col, imfptr, "up_axis", UI_ITEM_NONE, NULL, ICON_NONE);
|
||||
uiItemR(col, imfptr, "use_mesh_validate", UI_ITEM_NONE, NULL, ICON_NONE);
|
||||
}
|
||||
|
||||
static void wm_stl_import_draw(bContext *C, wmOperator *op)
|
||||
{
|
||||
PointerRNA ptr;
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
|
||||
files_drop_label_draw(C, op, ICON_FILE_3D, ".stl");
|
||||
ui_stl_import_settings(op->layout, &ptr);
|
||||
}
|
||||
|
||||
void WM_OT_stl_import(wmOperatorType *ot)
|
||||
{
|
||||
|
@ -94,11 +118,12 @@ void WM_OT_stl_import(wmOperatorType *ot)
|
|||
ot->description = "Import an STL file as an object";
|
||||
ot->idname = "WM_OT_stl_import";
|
||||
|
||||
ot->invoke = wm_stl_import_invoke;
|
||||
ot->invoke = wm_io_import_invoke;
|
||||
ot->exec = wm_stl_import_exec;
|
||||
ot->poll = WM_operator_winactive;
|
||||
ot->check = wm_stl_import_check;
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_PRESET;
|
||||
ot->ui = wm_stl_import_draw;
|
||||
ot->flag = OPTYPE_UNDO | OPTYPE_PRESET;
|
||||
|
||||
WM_operator_properties_filesel(ot,
|
||||
FILE_TYPE_FOLDER,
|
||||
|
@ -108,6 +133,7 @@ void WM_OT_stl_import(wmOperatorType *ot)
|
|||
WM_FILESEL_SHOW_PROPS,
|
||||
FILE_DEFAULTDISPLAY,
|
||||
FILE_SORT_DEFAULT);
|
||||
skip_filesel_props(ot, WM_FILESEL_FILEPATH | WM_FILESEL_FILES | WM_FILESEL_DIRECTORY);
|
||||
|
||||
RNA_def_float(ot->srna, "global_scale", 1.0f, 1e-6f, 1e6f, "Scale", "", 0.001f, 1000.0f);
|
||||
RNA_def_boolean(ot->srna,
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
# include "DEG_depsgraph.h"
|
||||
|
||||
# include "io_usd.hh"
|
||||
# include "io_utils.hh"
|
||||
# include "usd.h"
|
||||
|
||||
# include <cstdio>
|
||||
|
@ -386,7 +387,7 @@ static int wm_usd_import_invoke(bContext *C, wmOperator *op, const wmEvent *even
|
|||
options->as_background_job = true;
|
||||
op->customdata = options;
|
||||
|
||||
return WM_operator_filesel(C, op, event);
|
||||
return wm_io_import_invoke(C, op, event);
|
||||
}
|
||||
|
||||
static int wm_usd_import_exec(bContext *C, wmOperator *op)
|
||||
|
@ -525,11 +526,13 @@ static void wm_usd_import_cancel(bContext * /*C*/, wmOperator *op)
|
|||
free_operator_customdata(op);
|
||||
}
|
||||
|
||||
static void wm_usd_import_draw(bContext * /*C*/, wmOperator *op)
|
||||
static void wm_usd_import_draw(bContext *C, wmOperator *op)
|
||||
{
|
||||
uiLayout *layout = op->layout;
|
||||
PointerRNA *ptr = op->ptr;
|
||||
|
||||
files_drop_label_draw(C, op, ICON_FILE_3D, ".usd");
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
uiLayoutSetPropDecorate(layout, false);
|
||||
|
||||
|
@ -601,7 +604,7 @@ void WM_OT_usd_import(wmOperatorType *ot)
|
|||
ot->poll = WM_operator_winactive;
|
||||
ot->ui = wm_usd_import_draw;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_PRESET;
|
||||
ot->flag = OPTYPE_UNDO | OPTYPE_PRESET;
|
||||
|
||||
WM_operator_properties_filesel(ot,
|
||||
FILE_TYPE_FOLDER | FILE_TYPE_USD,
|
||||
|
@ -610,6 +613,7 @@ void WM_OT_usd_import(wmOperatorType *ot)
|
|||
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS,
|
||||
FILE_DEFAULTDISPLAY,
|
||||
FILE_SORT_DEFAULT);
|
||||
skip_filesel_props(ot, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH);
|
||||
|
||||
PropertyRNA *prop = RNA_def_string(ot->srna, "filter_glob", "*.usd", 0, "", "");
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#if defined(WITH_COLLADA) || defined(WITH_IO_GPENCIL) || defined(WITH_IO_WAVEFRONT_OBJ) || \
|
||||
defined(WITH_IO_PLY) || defined(WITH_IO_STL) || defined(WITH_USD)
|
||||
guishe marked this conversation as resolved
Brecht Van Lommel
commented
Remove these tests. The code may not be used if none of these are defined, but that's not a problem. Remove these tests. The code may not be used if none of these are defined, but that's not a problem.
|
||||
|
||||
# include "BKE_context.h"
|
||||
|
||||
# include "BLI_path_util.h"
|
||||
# include "BLI_string.h"
|
||||
# include "BLI_utildefines.h"
|
||||
|
||||
# include "BLT_translation.h"
|
||||
|
||||
# include "DNA_space_types.h"
|
||||
|
||||
# include "ED_fileselect.hh"
|
||||
|
||||
# include "RNA_access.hh"
|
||||
# include "RNA_define.hh"
|
||||
|
||||
# include "UI_interface.hh"
|
||||
|
||||
# include "WM_api.hh"
|
||||
|
||||
# include "io_utils.hh"
|
||||
|
||||
int wm_io_import_invoke(bContext *C, wmOperator *op, const wmEvent * /* event */)
|
||||
{
|
||||
char filepath[FILE_MAX];
|
||||
RNA_string_get(op->ptr, "filepath", filepath);
|
||||
|
||||
if (filepath[0]) {
|
||||
return WM_operator_props_dialog_popup(C, op, 300);
|
||||
}
|
||||
|
||||
WM_event_add_fileselect(C, op);
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
void skip_filesel_props(wmOperatorType *ot, const eFileSel_Flag flag)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
if (flag & WM_FILESEL_FILEPATH) {
|
||||
prop = RNA_struct_type_find_property(ot->srna, "filepath");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
if (flag & WM_FILESEL_FILENAME) {
|
||||
prop = RNA_struct_type_find_property(ot->srna, "filename");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
if (flag & WM_FILESEL_DIRECTORY) {
|
||||
prop = RNA_struct_type_find_property(ot->srna, "directory");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
if (flag & WM_FILESEL_FILES) {
|
||||
prop = RNA_struct_type_find_property(ot->srna, "files");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
if (flag & WM_FILESEL_RELPATH) {
|
||||
prop = RNA_struct_type_find_property(ot->srna, "relative_path");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
}
|
||||
|
||||
void files_drop_label_draw(bContext *C, wmOperator *op, int icon, const char *extension)
|
||||
{
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
|
||||
if (area->spacetype == SPACE_FILE) {
|
||||
return;
|
||||
}
|
||||
|
||||
char label[FILE_MAX];
|
||||
RNA_string_get(op->ptr, "filepath", label);
|
||||
|
||||
if (RNA_struct_find_property(op->ptr, "directory") &&
|
||||
RNA_collection_length(op->ptr, "files") > 1) {
|
||||
sprintf(label, "%d %s files dropped.", RNA_collection_length(op->ptr, "files"), extension);
|
||||
}
|
||||
|
||||
uiLayout *box = uiLayoutBox(op->layout);
|
||||
uiItemL(box, label, icon);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,19 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(WITH_COLLADA) || defined(WITH_IO_GPENCIL) || defined(WITH_IO_WAVEFRONT_OBJ) || \
|
||||
defined(WITH_IO_PLY) || defined(WITH_IO_STL) || defined(WITH_USD)
|
||||
|
||||
# include "WM_types.hh"
|
||||
|
||||
struct wmOperator;
|
||||
struct wmOperatorType;
|
||||
struct wmDrag;
|
||||
struct wmDropBox;
|
||||
|
||||
int wm_io_import_invoke(bContext *C, wmOperator *op, const wmEvent *event);
|
||||
void skip_filesel_props(wmOperatorType *ot, const eFileSel_Flag flag);
|
||||
void files_drop_label_draw(bContext *C, wmOperator *op, int icon, const char *extension);
|
||||
guishe marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
These names are bit generic to put in global namespace. The Maybe use a These names are bit generic to put in global namespace. The `wm_` prefix would also imply that the function is defined in the `window_manager_module`.
Maybe use a `io_util_` prefix?
|
||||
|
||||
#endif
|
|
@ -5913,7 +5913,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);
|
||||
}
|
||||
|
||||
|
|
|
@ -800,7 +800,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 */
|
||||
|
|
|
@ -726,9 +726,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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_paths(drag)[0].c_str());
|
||||
}
|
||||
|
||||
static bool text_drop_paste_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
|
||||
|
|
|
@ -929,9 +929,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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1282,6 +1282,138 @@ static void rna_Menu_bl_description_set(PointerRNA *ptr, const char *value)
|
|||
|
||||
/* UILayout */
|
||||
|
||||
/* File Drop */
|
||||
|
||||
static bool file_drop_poll(const bContext *C, FileDropType *file_drop_type, const char *extension)
|
||||
{
|
||||
extern FunctionRNA rna_FileDrop_poll_extension_func;
|
||||
|
||||
PointerRNA ptr;
|
||||
RNA_pointer_create(nullptr, file_drop_type->rna_ext.srna, nullptr, &ptr); /* dummy */
|
||||
/* RNA_struct_find_function(&ptr, "poll"); */
|
||||
FunctionRNA *func = &rna_FileDrop_poll_extension_func;
|
||||
|
||||
ParameterList list;
|
||||
RNA_parameter_list_create(&list, &ptr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
RNA_parameter_set_lookup(&list, "extension", &extension);
|
||||
file_drop_type->rna_ext.call((bContext *)C, &ptr, func, &list);
|
||||
|
||||
void *ret;
|
||||
RNA_parameter_get_lookup(&list, "visible", &ret);
|
||||
/* Get the value before freeing. */
|
||||
const bool is_visible = *(bool *)ret;
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
|
||||
return is_visible;
|
||||
}
|
||||
|
||||
static bool rna_FileDrop_unregister(Main * /*bmain*/, StructRNA *type)
|
||||
{
|
||||
FileDropType *file_drop_type = static_cast<FileDropType *>(RNA_struct_blender_type_get(type));
|
||||
|
||||
if (!file_drop_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SpaceType *space_type = BKE_spacetype_from_id(file_drop_type->space_type);
|
||||
if (!space_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RNA_struct_free_extension(type, &file_drop_type->rna_ext);
|
||||
RNA_struct_free(&BLENDER_RNA, type);
|
||||
|
||||
BLI_freelinkN(&space_type->file_drop_types, file_drop_type);
|
||||
|
||||
/* update while blender is running */
|
||||
WM_main_add_notifier(NC_WINDOW, nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static StructRNA *rna_FileDrop_register(Main *bmain,
|
||||
ReportList *reports,
|
||||
void *data,
|
||||
const char *identifier,
|
||||
StructValidateFunc validate,
|
||||
StructCallbackFunc call,
|
||||
StructFreeFunc free)
|
||||
{
|
||||
FileDropType dummy_file_drop_type = {};
|
||||
FileDrop dummy_file_drop = {};
|
||||
PointerRNA dummy_file_drop_ptr;
|
||||
dummy_file_drop.type = &dummy_file_drop_type;
|
||||
/* setup dummy file drop type to store static properties in */
|
||||
RNA_pointer_create(nullptr, &RNA_FileDrop, &dummy_file_drop, &dummy_file_drop_ptr);
|
||||
|
||||
bool have_function[1];
|
||||
|
||||
/* validate the python class */
|
||||
if (validate(&dummy_file_drop_ptr, data, have_function) != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (strlen(identifier) >= sizeof(dummy_file_drop_type.idname)) {
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"Registering file drop class: '%s' is too long, maximum length is %d",
|
||||
identifier,
|
||||
(int)sizeof(dummy_file_drop_type.idname));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SpaceType *space_type = BKE_spacetype_from_id(dummy_file_drop_type.space_type);
|
||||
if (!space_type) {
|
||||
BLI_assert_unreachable();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Check if we have registered this file drop type before, and remove it. */
|
||||
LISTBASE_FOREACH (FileDropType *, iter_file_drop_type, &space_type->file_drop_types) {
|
||||
if (STREQ(iter_file_drop_type->idname, dummy_file_drop_type.idname)) {
|
||||
if (iter_file_drop_type->rna_ext.srna) {
|
||||
rna_FileDrop_unregister(bmain, iter_file_drop_type->rna_ext.srna);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!RNA_struct_available_or_report(reports, dummy_file_drop_type.idname)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!RNA_struct_bl_idname_ok_or_report(reports, dummy_file_drop_type.idname, "_FDT_")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Create the new file drop type. */
|
||||
FileDropType *file_drop_type = MEM_cnew<FileDropType>(__func__);
|
||||
memcpy(file_drop_type, &dummy_file_drop_type, sizeof(*file_drop_type));
|
||||
|
||||
file_drop_type->rna_ext.srna = RNA_def_struct_ptr(
|
||||
&BLENDER_RNA, file_drop_type->idname, &RNA_FileDrop);
|
||||
file_drop_type->rna_ext.data = data;
|
||||
file_drop_type->rna_ext.call = call;
|
||||
file_drop_type->rna_ext.free = free;
|
||||
RNA_struct_blender_type_set(file_drop_type->rna_ext.srna, file_drop_type);
|
||||
|
||||
file_drop_type->poll_extension = have_function[0] ? file_drop_poll : nullptr;
|
||||
|
||||
BLI_addtail(&space_type->file_drop_types, file_drop_type);
|
||||
|
||||
/* update while blender is running */
|
||||
WM_main_add_notifier(NC_WINDOW, nullptr);
|
||||
|
||||
return file_drop_type->rna_ext.srna;
|
||||
}
|
||||
|
||||
static StructRNA *rna_FileDrop_refine(PointerRNA *file_drop_ptr)
|
||||
{
|
||||
FileDrop *file_drop = (FileDrop *)file_drop_ptr->data;
|
||||
return (file_drop && file_drop->type->rna_ext.srna) ? file_drop->type->rna_ext.srna :
|
||||
&RNA_FileDrop;
|
||||
}
|
||||
|
||||
static bool rna_UILayout_active_get(PointerRNA *ptr)
|
||||
{
|
||||
return uiLayoutGetActive(static_cast<uiLayout *>(ptr->data));
|
||||
|
@ -2073,6 +2205,61 @@ static void rna_def_menu(BlenderRNA *brna)
|
|||
RNA_define_verify_sdna(true);
|
||||
}
|
||||
|
||||
static void rna_def_file_drop(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "FileDrop", nullptr);
|
||||
RNA_def_struct_ui_text(srna, "File Drop Type", "File drop polling function class");
|
||||
RNA_def_struct_sdna(srna, "FileDrop");
|
||||
RNA_def_struct_refine_func(srna, "rna_FileDrop_refine");
|
||||
RNA_def_struct_register_funcs(srna, "rna_FileDrop_register", "rna_FileDrop_unregister", nullptr);
|
||||
RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
|
||||
RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT);
|
||||
/* registration */
|
||||
RNA_define_verify_sdna(false); /* not in sdna */
|
||||
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, nullptr, "type->idname");
|
||||
RNA_def_property_flag(prop, PROP_REGISTER);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"ID Name",
|
||||
"If this is set, the asset gets a custom ID, otherwise it takes the "
|
||||
"name of the class used to define the menu (for example, if the "
|
||||
"class name is \"OBJECT_FDT_hello\", and bl_idname is not set by the "
|
||||
"script, then bl_idname = \"OBJECT_FDT_hello\")");
|
||||
|
||||
brecht marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
I'm not sure about this mechanism. We don't have a good way to pass a list of strings here currently, but the easier workaround to me seems to have a string of extensions separated by I'm not sure about this mechanism. We don't have a good way to pass a list of strings here currently, but the easier workaround to me seems to have a string of extensions separated by `;` or something like that.
Guillermo Venegas
commented
I changed it to be just a string separated by I changed it to be just a string separated by `;`, and also eliminated the `IDProperty` because it was only used for that purpose.
|
||||
prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "type->space_type");
|
||||
RNA_def_property_enum_items(prop, rna_enum_space_type_items);
|
||||
RNA_def_property_flag(prop, PROP_REGISTER);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Space Type", "The space type where file dropped cin be used by the operator");
|
||||
|
||||
prop = RNA_def_property(srna, "bl_operator", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, nullptr, "type->op_name");
|
||||
RNA_def_property_flag(prop, PROP_REGISTER);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Operator", "Operator to call if the poll_extension is successful");
|
||||
|
||||
PropertyRNA *parm;
|
||||
FunctionRNA *func;
|
||||
|
||||
func = RNA_def_function(srna, "poll_extension", nullptr);
|
||||
RNA_def_function_ui_description(
|
||||
func, "If this method returns a non-null output, the file importer will be used");
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
|
||||
RNA_def_function_return(func, RNA_def_boolean(func, "visible", true, "", ""));
|
||||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
|
||||
|
||||
parm = RNA_def_string(
|
||||
func, "extension", nullptr, 256, "extension", "Extension to test for dropped file");
|
||||
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
|
||||
|
||||
RNA_define_verify_sdna(true);
|
||||
}
|
||||
|
||||
static void rna_def_asset_shelf(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
@ -2182,6 +2369,7 @@ void RNA_def_ui(BlenderRNA *brna)
|
|||
rna_def_header(brna);
|
||||
rna_def_menu(brna);
|
||||
rna_def_asset_shelf(brna);
|
||||
rna_def_file_drop(brna);
|
||||
}
|
||||
|
||||
#endif /* RNA_RUNTIME */
|
||||
|
|
|
@ -1405,13 +1405,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.
|
||||
|
|
|
@ -108,6 +108,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"
|
||||
|
@ -1129,10 +1130,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 {
|
||||
|
|
|
@ -768,29 +768,47 @@ 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 *extension = BLI_path_extension(paths[0]);
|
||||
blender::Vector<std::string> filtered_paths;
|
||||
for (auto path : paths) {
|
||||
const char *test_ext = BLI_path_extension(path);
|
||||
if (extension == test_ext || (extension && test_ext && STREQ(extension, test_ext))) {
|
||||
filtered_paths.append(path);
|
||||
}
|
||||
}
|
||||
const char *tooltip = paths[0];
|
||||
char tooltip_buffer[256];
|
||||
if (filtered_paths.size() > 1) {
|
||||
BLI_snprintf(tooltip_buffer,
|
||||
ARRAY_SIZE(tooltip_buffer),
|
||||
TIP_("Dragging %d %s files."),
|
||||
filtered_paths.size(),
|
||||
extension ? extension : TIP_("Folder"));
|
||||
tooltip = tooltip_buffer;
|
||||
}
|
||||
|
||||
wmDragPath *path_data = MEM_new<wmDragPath>(
|
||||
"wmDragPath", filtered_paths, tooltip, ED_path_extension_type(paths[0]));
|
||||
|
||||
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);
|
||||
return path_data->path;
|
||||
return path_data->paths.as_span();
|
||||
}
|
||||
|
||||
int WM_drag_get_path_file_type(const wmDrag *drag)
|
||||
|
@ -854,7 +872,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);
|
||||
|
|
|
@ -1511,11 +1511,12 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_pt
|
|||
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 pointer should point to string, it makes a copy. */
|
||||
break; /* only one drop element supported now */
|
||||
|
|
Use
IFACE_("Import %s")
for translation.