WIP: Experiment: Drop import operator helper and file drop type #111242

Closed
Guillermo Venegas wants to merge 23 commits from guishe/blender:drop-helper into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
14 changed files with 334 additions and 441 deletions
Showing only changes of commit 3875bf9610 - Show all commits

View File

@ -29,6 +29,18 @@ struct FileHandlerType {
/** RNA integration. */
ExtensionRNA rna_ext;
/** Returns a vector of indices on #paths of those file paths supported by the file handler. */
blender::Vector<int64_t> filter_supported_paths(const blender::Span<std::string> paths) const;
/** Return the import operator associated to the file handler if set and exists, otherwise
* #null_ptr. */
wmOperatorType *get_import_operator() const;
/* Creates a #PointerRNA for the #import_operator and fills it with all file paths supported by
* the file handler. */
PointerRNA import_operator_file_properties_create_ptr(
const blender::Span<std::string> paths) const;
};
/**
@ -49,3 +61,8 @@ void BKE_file_handler_remove(FileHandlerType *file_handler);
/** Return a reference of the #RawVector with all `file_handlers` registered. */
const blender::RawVector<std::unique_ptr<FileHandlerType>> &BKE_file_handlers();
/** Return a vector of file handlers that support any file path in #paths, has a valid
* #import_operator assigned and the call to #poll_drop returns #true. */
blender::Vector<FileHandlerType *> BKE_file_handlers_poll_file_drop(
const bContext *C, const blender::Span<std::string> paths);

View File

@ -31,6 +31,8 @@ set(INC
../../../intern/opensubdiv
../../../extern/fmtlib/include
../windowmanager
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
)

View File

@ -83,8 +83,6 @@ void BKE_blender_free()
IMB_moviecache_destruct();
BKE_node_system_exit();
BKE_file_handlers_free();
}
/** \} */

View File

@ -2,9 +2,15 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "WM_api.hh"
#include "WM_types.hh"
#include "BKE_file_handler.hh"
#include "BLI_string.h"
#include "RNA_access.hh"
static blender::RawVector<std::unique_ptr<FileHandlerType>> &file_handlers()
{
@ -57,3 +63,104 @@ void BKE_file_handler_remove(FileHandlerType *file_handler)
return test_file_handler.get() == file_handler;
});
}
blender::Vector<FileHandlerType *> BKE_file_handlers_poll_file_drop(
const bContext *C, const blender::Span<std::string> paths)
{
blender::Vector<std::string> path_extensions;
for (const std::string &path : paths) {
const char *extension = BLI_path_extension(path.c_str());
if (!extension) {
continue;
}
path_extensions.append_non_duplicates(extension);
}
blender::Vector<FileHandlerType *> result;
for (const std::unique_ptr<FileHandlerType> &file_handler_ptr : file_handlers()) {
FileHandlerType &file_handler = *file_handler_ptr;
const auto &file_extensions = file_handler.file_extensions;
const bool support_any_extension = std::any_of(
file_extensions.begin(),
file_extensions.end(),
[&path_extensions](const std::string &test_extension) {
return path_extensions.contains(test_extension);
});
if (!support_any_extension) {
continue;
}
if (!(file_handler.poll_drop && file_handler.poll_drop(C, &file_handler))) {
continue;
}
/* File handles can be registered without a import operator, or the import operator can be
* removed and the file handler can still be registered, filter too file handles with valid
* import operators. */
if (!file_handler.get_import_operator()) {
continue;
}
result.append(&file_handler);
}
return result;
}
blender::Vector<int64_t> FileHandlerType::filter_supported_paths(
const blender::Span<std::string> paths) const
{
blender::Vector<int64_t> indices;
for (const int idx : paths.index_range()) {
const char *extension = BLI_path_extension(paths[idx].c_str());
if (!extension) {
continue;
}
if (file_extensions.contains(extension)) {
indices.append(idx);
}
}
return indices;
}
wmOperatorType *FileHandlerType::get_import_operator() const
{
return WM_operatortype_find(import_operator, false);
}
PointerRNA FileHandlerType::import_operator_file_properties_create_ptr(
const blender::Span<std::string> paths) const
{
BLI_assert(get_import_operator());
PointerRNA props;
WM_operator_properties_create_ptr(&props, get_import_operator());
const auto suported_paths = filter_supported_paths(paths);
if (PropertyRNA *prop = RNA_struct_find_property(&props, "filepath")) {
RNA_string_set(&props, "filepath", paths[suported_paths[0]].c_str());
}
if (PropertyRNA *prop = RNA_struct_find_property(&props, "directory")) {
char dir[FILE_MAX];
BLI_path_split_dir_part(paths[0].c_str(), dir, sizeof(dir));
RNA_string_set(&props, "directory", dir);
RNA_collection_clear(&props, "files");
for (const auto &index : suported_paths) {
char file[FILE_MAX];
BLI_path_split_file_part(paths[index].c_str(), file, sizeof(file));
PointerRNA itemptr{};
RNA_collection_add(&props, "files", &itemptr);
RNA_string_set(&itemptr, "name", file);
}
}
return props;
}

View File

@ -17,6 +17,8 @@ set(INC
../../io/wavefront_obj
../../makesrna
../../windowmanager
../../../../extern/fmtlib/include
)
set(INC_SYS
@ -36,7 +38,7 @@ set(SRC
io_stl_ops.cc
io_usd.cc
io_utils.cc
io_drop_file_import.cc
io_drop_import_file.cc
io_alembic.hh
io_cache.hh
@ -48,7 +50,7 @@ set(SRC
io_stl_ops.hh
io_usd.hh
io_utils.hh
io_drop_file_import.hh
io_drop_import_file.hh
)
set(LIB
@ -57,6 +59,7 @@ set(LIB
PRIVATE bf::depsgraph
PRIVATE bf::dna
PRIVATE bf::intern::guardedalloc
extern_fmtlib
)
if(WITH_OPENCOLLADA)

View File

@ -1,228 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "DNA_space_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_file_handler.hh"
#include "BKE_main.h"
#include "BKE_preferences.h"
#include "ED_fileselect.hh"
#include "RNA_access.hh"
#include "RNA_define.hh"
#include "WM_api.hh"
#include "WM_types.hh"
#include "UI_interface.hh"
#include "io_drop_file_import.hh"
static bool poll_extension(blender::Span<bFileExtension> file_extensions, const char *extension)
{
for (auto &file_extension : file_extensions) {
if (STREQ(extension, file_extension.extension)) {
return true;
}
}
return false;
}
static blender::Vector<FileHandlerType *> poll_file_handlers_for_extension(bContext *C,
const char *extension)
{
blender::Vector<FileHandlerType *> result;
for (auto *file_handler : BKE_file_handlers()) {
if (!poll_extension(file_handler->file_extensions, extension)) {
continue;
}
if (!(file_handler->poll_drop && file_handler->poll_drop(C, file_handler))) {
continue;
}
wmOperatorType *test_operator = WM_operatortype_find(file_handler->import_operator, false);
if (!test_operator) {
/* Discard if operators that does not exist. */
continue;
}
result.append(file_handler);
}
return result;
}
static PointerRNA copy_file_properties_to_operator_type_pointer(wmOperator *op, wmOperatorType *ot)
{
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);
}
}
return op_props;
}
static int wm_drop_file_import_exec(bContext *C, wmOperator *op)
{
char extension[MAX_NAME];
RNA_string_get(op->ptr, "extension", extension);
blender::Vector<FileHandlerType *> file_handlers = poll_file_handlers_for_extension(C,
extension);
if (file_handlers.size() == 0) {
return OPERATOR_CANCELLED;
}
wmOperatorType *ot = WM_operatortype_find(file_handlers[0]->import_operator, false);
PointerRNA op_props = copy_file_properties_to_operator_type_pointer(op, ot);
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props, nullptr);
WM_operator_properties_free(&op_props);
return OPERATOR_FINISHED;
}
static int wm_drop_file_import_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
{
char extension[MAX_NAME];
RNA_string_get(op->ptr, "extension", extension);
blender::Vector<FileHandlerType *> file_handlers = poll_file_handlers_for_extension(C,
extension);
if (file_handlers.size() == 1) {
return wm_drop_file_import_exec(C, op);
}
uiPopupMenu *pup = UI_popup_menu_begin(C, "", ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup);
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
for (auto *file_handler : file_handlers) {
wmOperatorType *ot = WM_operatortype_find(file_handler->import_operator, false);
PointerRNA op_props = copy_file_properties_to_operator_type_pointer(op, ot);
char *import_label = BLI_sprintfN(IFACE_("Import %s"), file_handler->label);
uiItemFullO_ptr(layout,
ot,
import_label,
ICON_NONE,
static_cast<IDProperty *>(op_props.data),
WM_OP_INVOKE_DEFAULT,
UI_ITEM_NONE,
nullptr);
MEM_freeN(import_label);
}
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
}
void WM_OT_drop_file_import(wmOperatorType *ot)
{
ot->name = "Drop File to Import";
ot->description =
"Operator that handles file drops and uses file handler information to call "
"operators that can import a file with extension.";
ot->idname = "WM_OT_drop_file_import";
ot->flag = OPTYPE_INTERNAL;
ot->exec = wm_drop_file_import_exec;
ot->invoke = wm_drop_file_import_invoke;
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 drop_file_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 drop_file_poll(bContext *C, wmDrag *drag, const wmEvent * /*event*/)
{
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 && poll_file_handlers_for_extension(C, extension).size() > 0;
}
static char *drop_file_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());
blender::Vector<FileHandlerType *> file_handlers = poll_file_handlers_for_extension(C,
extension);
if (file_handlers.size() == 0) {
return nullptr;
}
if (file_handlers.size() == 1) {
return BLI_sprintfN("Import %s", file_handlers[0]->label);
}
return BLI_strdup("Multiple operators can handle this file(s), drop to pick which to use");
}
void ED_dropbox_drop_file_import()
{
ListBase *lb = WM_dropboxmap_find("Window", 0, 0);
WM_dropbox_add(
lb, "WM_OT_drop_file_import", drop_file_poll, drop_file_copy, nullptr, drop_file_tooltip);
}

View File

@ -0,0 +1,186 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "DNA_space_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_path_util.h"
#include "BLT_translation.h"
#include "BKE_context.hh"
#include "BKE_file_handler.hh"
#include "BKE_main.hh"
#include "BKE_preferences.h"
#include "ED_fileselect.hh"
#include <fmt/format.h>
#include "RNA_access.hh"
#include "RNA_define.hh"
#include "WM_api.hh"
#include "WM_types.hh"
#include "UI_interface.hh"
#include "io_drop_import_file.hh"
/* Retuns the list of file paths stored in #WM_OT_drop_import_file operator properties. */
static blender::Vector<std::string> drop_import_file_paths(const wmOperator *op)
{
blender::Vector<std::string> result;
char dir[FILE_MAX], file[FILE_MAX];
RNA_string_get(op->ptr, "directory", dir);
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "files");
int files_len = RNA_property_collection_length(op->ptr, prop);
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", file);
char file_path[FILE_MAX];
BLI_path_join(file_path, sizeof(file_path), dir, file);
result.append(file_path);
}
return result;
}
static int wm_drop_import_file_exec(bContext *C, wmOperator *op)
{
auto paths = drop_import_file_paths(op);
if (paths.size() < 1) {
return OPERATOR_CANCELLED;
}
auto file_handlers = BKE_file_handlers_poll_file_drop(C, paths);
if (file_handlers.size() == 0) {
return OPERATOR_CANCELLED;
}
PointerRNA file_props = file_handlers[0]->import_operator_file_properties_create_ptr(paths);
WM_operator_name_call_ptr(
C, file_handlers[0]->get_import_operator(), WM_OP_INVOKE_DEFAULT, &file_props, nullptr);
WM_operator_properties_free(&file_props);
return OPERATOR_FINISHED;
}
static int wm_drop_import_file_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
{
const auto paths = drop_import_file_paths(op);
if (paths.size() < 1) {
return OPERATOR_CANCELLED;
}
auto file_handlers = BKE_file_handlers_poll_file_drop(C, paths);
/** Execute directly if the files are only supported by a file handler. */
if (file_handlers.size() == 1) {
return wm_drop_import_file_exec(C, op);
}
/** Create a menu with file handler import operators that can support the files and let user
* decide what to use. */
uiPopupMenu *pup = UI_popup_menu_begin(C, "", ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup);
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
for (auto *file_handler : file_handlers) {
PointerRNA file_props = file_handler->import_operator_file_properties_create_ptr(paths);
std::string label = fmt::format(TIP_("Import {}"), file_handler->label);
uiItemFullO_ptr(layout,
file_handler->get_import_operator(),
label.c_str(),
ICON_NONE,
static_cast<IDProperty *>(file_props.data),
WM_OP_INVOKE_DEFAULT,
UI_ITEM_NONE,
nullptr);
}
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
}
void WM_OT_drop_import_file(wmOperatorType *ot)
{
ot->name = "Drop to Import File";
ot->description = "Manages file ";
ot->idname = "WM_OT_drop_import_file";
ot->flag = OPTYPE_INTERNAL;
ot->exec = wm_drop_import_file_exec;
ot->invoke = wm_drop_import_file_invoke;
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 drop_import_file_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *drop)
{
const auto paths = WM_drag_get_paths(drag);
char dir[FILE_MAX];
BLI_path_split_dir_part(paths[0].c_str(), dir, sizeof(dir));
RNA_string_set(drop->ptr, "directory", dir);
RNA_collection_clear(drop->ptr, "files");
for (const auto &path : paths) {
char file[FILE_MAX];
BLI_path_split_file_part(path.c_str(), file, sizeof(file));
PointerRNA itemptr{};
RNA_collection_add(drop->ptr, "files", &itemptr);
RNA_string_set(&itemptr, "name", file);
}
}
static bool drop_import_file_poll(bContext *C, wmDrag *drag, const wmEvent * /*event*/)
{
if (drag->type != WM_DRAG_PATH) {
return false;
}
const auto paths = WM_drag_get_paths(drag);
return BKE_file_handlers_poll_file_drop(C, paths).size() > 0;
}
static char *drop_import_file_tooltip(bContext *C,
wmDrag *drag,
const int /*xy*/[2],
wmDropBox * /*drop*/)
{
const auto paths = WM_drag_get_paths(drag);
const auto file_handlers = BKE_file_handlers_poll_file_drop(C, paths);
if (file_handlers.size() == 0) {
return nullptr;
}
if (file_handlers.size() == 1) {
std::string label = fmt::format(TIP_("Import {}"), file_handlers[0]->label);
return BLI_strdup(label.c_str());
}
return BLI_strdup(TIP_("Multiple file handlers can be used, drop to pick which to use"));
}
void ED_dropbox_drop_import_file()
{
ListBase *lb = WM_dropboxmap_find("Window", 0, 0);
WM_dropbox_add(lb,
"WM_OT_drop_import_file",
drop_import_file_poll,
drop_import_file_copy,
nullptr,
drop_import_file_tooltip);
}

View File

@ -4,5 +4,5 @@
struct wmOperatorType;
void WM_OT_drop_file_import(wmOperatorType *ot);
void ED_dropbox_drop_file_import();
void WM_OT_drop_import_file(wmOperatorType *ot);
void ED_dropbox_drop_import_file();

View File

@ -23,7 +23,7 @@
#endif
#include "io_cache.hh"
#include "io_drop_file_import.hh"
#include "io_drop_import_file.hh"
#include "io_gpencil.hh"
#include "io_obj.hh"
#include "io_ply_ops.hh"
@ -75,6 +75,6 @@ void ED_operatortypes_io()
WM_operatortype_append(WM_OT_stl_import);
WM_operatortype_append(WM_OT_stl_export);
#endif
WM_operatortype_append(WM_OT_drop_file_import);
ED_dropbox_drop_file_import();
WM_operatortype_append(WM_OT_drop_import_file);
ED_dropbox_drop_import_file();
}

View File

@ -7,9 +7,8 @@
*/
#ifdef WITH_IO_STL
# include "BLT_translation.h"
# include "BKE_context.h"
# include "BKE_context.hh"
# include "BKE_report.h"
# include "WM_api.hh"
@ -23,11 +22,14 @@
# include "RNA_access.hh"
# include "RNA_define.hh"
# include "BLT_translation.h"
# include "UI_interface.hh"
# include "UI_resources.hh"
# include "IO_stl.hh"
# include "io_stl_ops.hh"
# include "io_utils.hh"
static int wm_stl_export_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
{
@ -174,6 +176,10 @@ void WM_OT_stl_export(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN);
}
static int wm_stl_import_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
return WM_operator_filesel(C, op, event);
}
static int wm_stl_import_exec(bContext *C, wmOperator *op)
{
@ -231,6 +237,7 @@ 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);
@ -262,7 +269,7 @@ void WM_OT_stl_import(wmOperatorType *ot)
ot->description = "Import an STL file as an object";
ot->idname = "WM_OT_stl_import";
ot->invoke = io_util_import_invoke;
ot->invoke = wm_stl_import_invoke;
ot->exec = wm_stl_import_exec;
ot->poll = WM_operator_winactive;
ot->check = wm_stl_import_check;

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_context.h"
#include "BKE_context.hh"
guishe marked this conversation as resolved

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 "BLI_path_util.h"
#include "BLI_string.h"

View File

@ -796,11 +796,6 @@ typedef struct AssetShelf {
char _pad[6];
} AssetShelf;
typedef struct FileHandler {
DNA_DEFINE_CXX_METHODS(FileHandler)
struct FileHandlerType *type; /* runtime */
} FileHandler;
/**
* Region-data for the main asset shelf region (#RGN_TYPE_ASSET_SHELF). Managed by the asset shelf
* internals.

View File

@ -16,7 +16,6 @@
#include "BKE_file_handler.hh"
#include "BKE_idprop.h"
#include "BKE_screen.hh"
#include "BLI_string.h"
#include "BLI_listbase.h"
@ -1284,137 +1283,6 @@ static void rna_Menu_bl_description_set(PointerRNA *ptr, const char *value)
BLI_assert_msg(0, "setting the bl_description on a non-builtin menu");
}
}
/* File Handler */
static bool file_handler_poll_drop(const bContext *C, FileHandlerType *file_handler_type)
{
extern FunctionRNA rna_FileHandler_poll_drop_func;
PointerRNA ptr = RNA_pointer_create(
nullptr, file_handler_type->rna_ext.srna, nullptr); /* dummy */
FunctionRNA *func = &rna_FileHandler_poll_drop_func;
ParameterList list;
RNA_parameter_list_create(&list, &ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
file_handler_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_FileHandler_unregister(Main * /*bmain*/, StructRNA *type)
{
FileHandlerType *file_handler_type = static_cast<FileHandlerType *>(
RNA_struct_blender_type_get(type));
if (!file_handler_type) {
return false;
}
RNA_struct_free_extension(type, &file_handler_type->rna_ext);
RNA_struct_free(&BLENDER_RNA, type);
BKE_file_handler_remove(file_handler_type);
return true;
}
static StructRNA *rna_FileHandler_register(Main *bmain,
ReportList *reports,
void *data,
const char *identifier,
StructValidateFunc validate,
StructCallbackFunc call,
StructFreeFunc free)
{
FileHandlerType dummy_file_handler_type{};
FileHandler dummy_file_handler{};
dummy_file_handler.type = &dummy_file_handler_type;
/* setup dummy file handler type to store static properties in */
PointerRNA dummy_file_handler_ptr = RNA_pointer_create(
nullptr, &RNA_FileHandler, &dummy_file_handler);
bool have_function[1];
/* validate the python class */
if (validate(&dummy_file_handler_ptr, data, have_function) != 0) {
return nullptr;
}
if (strlen(identifier) >= sizeof(dummy_file_handler_type.idname)) {
BKE_reportf(reports,
RPT_ERROR,
"Registering file handler class: '%s' is too long, maximum length is %d",
identifier,
(int)sizeof(dummy_file_handler_type.idname));
return nullptr;
}
/* Check if we have registered this file handler type before, and remove it. */
for (auto *iter_file_handler_type : BKE_file_handlers()) {
if (STREQ(iter_file_handler_type->idname, dummy_file_handler_type.idname)) {
if (iter_file_handler_type->rna_ext.srna) {
rna_FileHandler_unregister(bmain, iter_file_handler_type->rna_ext.srna);
}
break;
}
}
if (!RNA_struct_available_or_report(reports, dummy_file_handler_type.idname)) {
return nullptr;
}
if (!RNA_struct_bl_idname_ok_or_report(reports, dummy_file_handler_type.idname, "_FH_")) {
return nullptr;
}
/* Create the new file handler type. */
FileHandlerType *file_handler_type = MEM_new<FileHandlerType>(__func__);
*file_handler_type = dummy_file_handler_type;
/* Gather all extensions from a string into a list. */
const char char_separator = ';';
const char *char_begin = file_handler_type->file_extensions_str;
const char *char_end = BLI_strchr_or_end(char_begin, char_separator);
while (char_begin[0]) {
if (char_end - char_begin > 1) {
bFileExtension extension;
BLI_strncpy(extension.extension, char_begin, char_end - char_begin + 1);
file_handler_type->file_extensions.append(extension);
}
char_begin = char_end[0] ? char_end + 1 : char_end;
char_end = BLI_strchr_or_end(char_begin, char_separator);
}
file_handler_type->rna_ext.srna = RNA_def_struct_ptr(
&BLENDER_RNA, file_handler_type->idname, &RNA_FileHandler);
file_handler_type->rna_ext.data = data;
file_handler_type->rna_ext.call = call;
file_handler_type->rna_ext.free = free;
RNA_struct_blender_type_set(file_handler_type->rna_ext.srna, file_handler_type);
file_handler_type->poll_drop = have_function[0] ? file_handler_poll_drop : nullptr;
BKE_file_handler_add(file_handler_type);
return file_handler_type->rna_ext.srna;
}
static StructRNA *rna_FileHandler_refine(PointerRNA *file_handler_ptr)
{
FileHandler *file_handler = (FileHandler *)file_handler_ptr->data;
return (file_handler && file_handler->type->rna_ext.srna) ? file_handler->type->rna_ext.srna :
&RNA_FileHandler;
}
/* UILayout */
@ -2340,66 +2208,6 @@ static void rna_def_menu(BlenderRNA *brna)
RNA_define_verify_sdna(true);
}
static void rna_def_file_handler(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "FileHandler", nullptr);
RNA_def_struct_ui_text(srna, "File Handler Type", "I/O File handler");
RNA_def_struct_sdna(srna, "FileHandler");
RNA_def_struct_refine_func(srna, "rna_FileHandler_refine");
RNA_def_struct_register_funcs(
srna, "rna_FileHandler_register", "rna_FileHandler_unregister", nullptr);
RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT);
/* registration */
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 file handler gets a custom ID, otherwise it takes the "
"name of the class used to define the file handler (for example, if the "
"class name is \"OBJECT_FH_hello\", and bl_idname is not set by the "
"script, then bl_idname = \"OBJECT_FH_hello\")");
prop = RNA_def_property(srna, "bl_import_operator", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, nullptr, "type->import_operator");
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
RNA_def_property_ui_text(
prop,
"Operator",
"Operator that can handle import files with extension in bl_file_extensions");
prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, nullptr, "type->label");
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_def_property_ui_text(prop, "Label", "The file handler label");
prop = RNA_def_property(srna, "bl_file_extensions", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, nullptr, "type->file_extensions_str");
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_def_property_ui_text(prop,
"File Extensions",
"List of file extensions supported separated by semicolon.\n"
"Example \".blend;.ble\"");
PropertyRNA *parm;
FunctionRNA *func;
func = RNA_def_function(srna, "poll_drop", nullptr);
RNA_def_function_ui_description(
func, "If this method returns a non-null output, then the file hanlder can 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);
}
static void rna_def_asset_shelf(BlenderRNA *brna)
{
StructRNA *srna;

View File

@ -214,8 +214,6 @@ void WM_init(bContext *C, int argc, const char **argv)
wm_operatortype_init();
wm_operatortypes_register();
BKE_file_handlers_init();
WM_paneltype_init(); /* Lookup table only. */
WM_menutype_init();
WM_uilisttype_init();