IO: Add initial support for File Handlers registration #112466

Merged
Jesse Yurkovich merged 15 commits from guishe/blender:file-handler into main 2023-12-09 05:06:24 +01:00
8 changed files with 422 additions and 1 deletions

View File

@ -1208,6 +1208,10 @@ class AssetShelf(StructRNA, metaclass=RNAMeta):
__slots__ = ()
class FileHandler(StructRNA, metaclass=RNAMeta):
__slots__ = ()
class NodeTree(bpy_types.ID, metaclass=RNAMetaPropGroup):
__slots__ = ()

View File

@ -0,0 +1,51 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_vector.hh"
#include "DNA_windowmanager_types.h"
#include "RNA_types.hh"
#define FH_MAX_FILE_EXTENSIONS_STR 512
guishe marked this conversation as resolved Outdated

Use /** */ doxygen syntax, put all comments on top.

See also https://wiki.blender.org/wiki/Style_Guide/C_Cpp#Comments

Use `/** */` doxygen syntax, put all comments on top. See also https://wiki.blender.org/wiki/Style_Guide/C_Cpp#Comments
struct FileHandlerType {
/** Unique name. */
char idname[OP_MAX_TYPENAME];
/** For UI text. */
char label[OP_MAX_TYPENAME];
guishe marked this conversation as resolved Outdated

Should also document the expected format of this string (separator, with or without dot, etc.)

Should also document the expected format of this string (separator, with or without dot, etc.)
/** Import operator name. */
guishe marked this conversation as resolved Outdated

I don't think 64 chars is enough here? That's max 12 3-chars extensions... E.g. a handler for image files may support tens of them...

Think it needs its own define, probably at 256 or 512 chars?

I don't think 64 chars is enough here? That's max 12 3-chars extensions... E.g. a handler for image files may support tens of them... Think it needs its own define, probably at 256 or 512 chars?
char import_operator[OP_MAX_TYPENAME];
guishe marked this conversation as resolved Outdated

picky and be separated by

*picky* `and be separated by`
/** Formatted string of file extensions supported by the file handler, each extension should
* start with a `.` and be separated by `;`. For Example: `".blend;.ble"`. */
char file_extensions_str[FH_MAX_FILE_EXTENSIONS_STR];
/** Check if file handler can be used on file drop. */
bool (*poll_drop)(const struct bContext *C, FileHandlerType *file_handle_type);
/** List of file extensions supported by the file handler. */
blender::Vector<std::string> file_extensions;
guishe marked this conversation as resolved Outdated

bFileExtension can just be a std::string?

`bFileExtension` can just be a `std::string`?
/** RNA integration. */
guishe marked this conversation as resolved Outdated

All of these functions need to be properly documented.

All of these functions need to be properly documented.
ExtensionRNA rna_ext;
};
/**
* Adds a new `file_handler` to the `file_handlers` list, also loads all the file extensions from
* the formatted `FileHandlerType.file_extensions_str` string to `FileHandlerType.file_extensions`
* list.
*
* The new `file_handler` is expected to have a unique `FileHandlerType.idname`.
*/
void BKE_file_handler_add(std::unique_ptr<FileHandlerType> file_handler);
/** Returns a `file_handler` that have a specific `idname`, otherwise return `nullptr`. */
FileHandlerType *BKE_file_handler_find(const char *idname);
/** Removes and frees a specific `file_handler` from the `file_handlers` list, the `file_handler`
* pointer will be not longer valid for use. */
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();

View File

@ -129,6 +129,7 @@ set(SRC
intern/fcurve.cc
intern/fcurve_cache.cc
intern/fcurve_driver.cc
intern/file_handler.cc
intern/fluid.cc
intern/fmodifier.cc
intern/freestyle.cc
@ -385,6 +386,7 @@ set(SRC
BKE_effect.h
BKE_fcurve.h
BKE_fcurve_driver.h
BKE_file_handler.hh
BKE_fluid.h
BKE_freestyle.h
BKE_geometry_fields.hh
@ -851,6 +853,7 @@ if(WITH_GTESTS)
intern/main_test.cc
intern/nla_test.cc
intern/tracking_test.cc
intern/file_handler_test.cc
)
set(TEST_INC
../editors/include

View File

@ -0,0 +1,59 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_file_handler.hh"
brecht marked this conversation as resolved Outdated

I think this can be simplified to static blender::Vector<FileHandlerType> file_handlers. For new C++ we should try to avoid this kind of manual memory allocation.

The only thing is that it should be defined inside a function, so that it is lazily initialized, after the memory allocator is initialized.

I think this can be simplified to `static blender::Vector<FileHandlerType> file_handlers`. For new C++ we should try to avoid this kind of manual memory allocation. The only thing is that it should be defined inside a function, so that it is lazily initialized, after the memory allocator is initialized.

I had to use static blender::RawVector<std::unique_ptr<FileHandlerType>> file_handlers;
Vector will not be released on closing
And had to use a unique_ptr, the RNAStruc pointer can be invalid if the array is rearranged (by removing or adding new elements) with just RawVector<FileHandlerType>

I had to use `static blender::RawVector<std::unique_ptr<FileHandlerType>> file_handlers;` `Vector` will not be released on closing And had to use a `unique_ptr`, the RNAStruc pointer can be invalid if the array is rearranged (by removing or adding new elements) with just `RawVector<FileHandlerType>`

Ok, that makes sense. Calling clear_and_shrink on Vector would have worked as well.

Ok, that makes sense. Calling `clear_and_shrink` on `Vector` would have worked as well.
#include "BLI_string.h"
static blender::RawVector<std::unique_ptr<FileHandlerType>> &file_handlers()
{
static blender::RawVector<std::unique_ptr<FileHandlerType>> file_handlers;
return file_handlers;
}
brecht marked this conversation as resolved Outdated

I don't think it's necessary to allocate another vector, can't this just return a const RawVector directly? It's less convenient, but I don't think we should be making copies just to iterate over this.

I don't think it's necessary to allocate another vector, can't this just return a `const RawVector` directly? It's less convenient, but I don't think we should be making copies just to iterate over this.

My concern was more about using unique_ptr, but returning the RawVector as a const disables the data ownership transfer, so it really shouldn't be a problem.

My concern was more about using `unique_ptr`, but returning the RawVector as a const disables the data ownership transfer, so it really shouldn't be a problem.
const blender::RawVector<std::unique_ptr<FileHandlerType>> &BKE_file_handlers()
{
return file_handlers();
}
FileHandlerType *BKE_file_handler_find(const char *name)
{
auto itr = std::find_if(file_handlers().begin(),
file_handlers().end(),
[name](const std::unique_ptr<FileHandlerType> &file_handler) {
return STREQ(name, file_handler->idname);
});
if (itr != file_handlers().end()) {
return itr->get();
}
return nullptr;
}
void BKE_file_handler_add(std::unique_ptr<FileHandlerType> file_handler)
guishe marked this conversation as resolved Outdated

Useless empty line

Useless empty line
{
BLI_assert(BKE_file_handler_find(file_handler->idname) != nullptr);
/** Load all extensions from the string list into the list. */
const char char_separator = ';';
const char *char_begin = file_handler->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) {
std::string file_extension(char_begin, char_end - char_begin);
file_handler->file_extensions.append(file_extension);
}
char_begin = char_end[0] ? char_end + 1 : char_end;
char_end = BLI_strchr_or_end(char_begin, char_separator);
}
file_handlers().append(std::move(file_handler));
}
void BKE_file_handler_remove(FileHandlerType *file_handler)
{
file_handlers().remove_if(
[file_handler](const std::unique_ptr<FileHandlerType> &test_file_handler) {
return test_file_handler.get() == file_handler;
});
}

View File

@ -0,0 +1,113 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: Apache-2.0 */
#include "BKE_file_handler.hh"
#include "testing/testing.h"
namespace blender::tests {
#define MAX_FILE_HANDLERS_TEST_SIZE 8
static FileHandlerType *file_handlers[MAX_FILE_HANDLERS_TEST_SIZE];
guishe marked this conversation as resolved Outdated

Would recommend rather using a #define here, easier to manage if this number needs to be changed later. 'Magic numbers' should be avoided as much as possible.

Would recommend rather using a `#define` here, easier to manage if this number needs to be changed later. 'Magic numbers' should be avoided as much as possible.
static void file_handler_add_test(const int test_number,
const char *idname,
const char *label,
const char *file_extensions_str,
blender::Vector<std::string> expected_file_extensions)
{
EXPECT_LE(test_number, MAX_FILE_HANDLERS_TEST_SIZE);
EXPECT_GE(test_number, 1);
guishe marked this conversation as resolved Outdated

Would add a check here that test_number <= <size of file_handlers> (using the #defined value for the size of this static array, as suggested above).

Would add a check here that `test_number <= <size of file_handlers>` (using the `#define`d value for the size of this static array, as suggested above).
EXPECT_EQ(BKE_file_handlers().size(), test_number - 1);
std::unique_ptr<FileHandlerType> file_handler = std::make_unique<FileHandlerType>();
file_handlers[test_number - 1] = file_handler.get();
strcpy(file_handler->idname, idname);
strcpy(file_handler->file_extensions_str, file_extensions_str);
strcpy(file_handler->label, label);
BKE_file_handler_add(std::move(file_handler));
EXPECT_EQ(BKE_file_handlers().size(), test_number);
EXPECT_EQ(BKE_file_handlers()[test_number - 1].get(), file_handlers[test_number - 1]);
EXPECT_EQ(BKE_file_handlers()[test_number - 1]->file_extensions, expected_file_extensions);
}
TEST(file_handler, add)
{
file_handler_add_test(1,
"Test_FH_blender1",
"File Handler Test 1",
".blender;.blend;.ble",
guishe marked this conversation as resolved
Review

This label and the next two ones seem to be off-by-one, is this expected? or copy-paste glitch?

This label and the next two ones seem to be off-by-one, is this expected? or copy-paste glitch?
{".blender", ".blend", ".ble"});
file_handler_add_test(2, "Test_FH_blender2", "File Handler Test 2", ".ble", {".ble"});
file_handler_add_test(3, "Test_FH_blender3", "File Handler Test 3", ";;.ble", {".ble"});
file_handler_add_test(4, "Test_FH_blender4", "File Handler Test 4", ";.ble;", {".ble"});
file_handler_add_test(5, "Test_FH_blender5", "File Handler Test 5", "d", {});
file_handler_add_test(6, "Test_FH_blender6", "File Handler Test 6", ";;", {});
file_handler_add_test(7, "Test_FH_blender7", "File Handler Test 7", ".", {});
file_handler_add_test(8, "Test_FH_blender8", "File Handler Test 8", "", {});
}
TEST(file_handler, find)
guishe marked this conversation as resolved
Review

Useless empty line ;)

Useless empty line ;)
{
EXPECT_EQ(BKE_file_handlers().size(), MAX_FILE_HANDLERS_TEST_SIZE);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender1"), file_handlers[0]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender2"), file_handlers[1]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender3"), file_handlers[2]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender4"), file_handlers[3]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender5"), file_handlers[4]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender6"), file_handlers[5]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender7"), file_handlers[6]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender8"), file_handlers[7]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blende"), nullptr);
EXPECT_EQ(BKE_file_handler_find("TstFH_blen"), nullptr);
}
TEST(file_handler, remove)
{
EXPECT_EQ(BKE_file_handlers().size(), MAX_FILE_HANDLERS_TEST_SIZE);
BKE_file_handler_remove(BKE_file_handler_find("Test_FH_blender2"));
EXPECT_EQ(BKE_file_handlers().size(), MAX_FILE_HANDLERS_TEST_SIZE - 1);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender2"), nullptr);
/** `FileHandlerType` pointer in `file_handlers[1]` is not longer valid. */
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender1"), file_handlers[0]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender3"), file_handlers[2]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender4"), file_handlers[3]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender5"), file_handlers[4]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender6"), file_handlers[5]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender7"), file_handlers[6]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender8"), file_handlers[7]);
EXPECT_EQ(BKE_file_handlers()[0].get(), file_handlers[0]);
EXPECT_EQ(BKE_file_handlers()[1].get(), file_handlers[2]);
EXPECT_EQ(BKE_file_handlers()[2].get(), file_handlers[3]);
EXPECT_EQ(BKE_file_handlers()[3].get(), file_handlers[4]);
EXPECT_EQ(BKE_file_handlers()[4].get(), file_handlers[5]);
EXPECT_EQ(BKE_file_handlers()[5].get(), file_handlers[6]);
EXPECT_EQ(BKE_file_handlers()[6].get(), file_handlers[7]);
BKE_file_handler_remove(BKE_file_handler_find("Test_FH_blender8"));
EXPECT_EQ(BKE_file_handlers().size(), MAX_FILE_HANDLERS_TEST_SIZE - 2);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender8"), nullptr);
/** `FileHandlerType` pointer in `file_handlers[7]` is not longer valid. */
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender1"), file_handlers[0]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender3"), file_handlers[2]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender4"), file_handlers[3]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender5"), file_handlers[4]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender6"), file_handlers[5]);
EXPECT_EQ(BKE_file_handler_find("Test_FH_blender7"), file_handlers[6]);
EXPECT_EQ(BKE_file_handlers()[0].get(), file_handlers[0]);
EXPECT_EQ(BKE_file_handlers()[1].get(), file_handlers[2]);
EXPECT_EQ(BKE_file_handlers()[2].get(), file_handlers[3]);
EXPECT_EQ(BKE_file_handlers()[3].get(), file_handlers[4]);
EXPECT_EQ(BKE_file_handlers()[4].get(), file_handlers[5]);
EXPECT_EQ(BKE_file_handlers()[5].get(), file_handlers[6]);
}
} // namespace blender::tests

View File

@ -822,3 +822,9 @@ typedef enum AssetShelfSettings_DisplayFlag {
ASSETSHELF_SHOW_NAMES = (1 << 0),
} AssetShelfSettings_DisplayFlag;
ENUM_OPERATORS(AssetShelfSettings_DisplayFlag, ASSETSHELF_SHOW_NAMES);
typedef struct FileHandler {
DNA_DEFINE_CXX_METHODS(FileHandler)
/** Runtime. */
struct FileHandlerType *type;
} FileHandler;

View File

@ -13,6 +13,7 @@
#include "BLT_translation.h"
#include "BKE_file_handler.hh"
#include "BKE_idprop.h"
#include "BKE_screen.hh"
@ -1452,6 +1453,122 @@ static void rna_UILayout_property_decorate_set(PointerRNA *ptr, bool value)
uiLayoutSetPropDecorate(static_cast<uiLayout *>(ptr->data), value);
}
/* 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, "is_usable", &ret);
/* Get the value before freeing. */
const bool is_usable = *(bool *)ret;
RNA_parameter_list_free(&list);
return is_usable;
}
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 there is a file handler registered with the same `idname`, and remove it. */
auto registered_file_handler = BKE_file_handler_find(dummy_file_handler_type.idname);
if (registered_file_handler) {
rna_FileHandler_unregister(bmain, registered_file_handler->rna_ext.srna);
}
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. */
std::unique_ptr<FileHandlerType> file_handler_type = std::make_unique<FileHandlerType>();
*file_handler_type = dummy_file_handler_type;
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.get());
file_handler_type->poll_drop = have_function[0] ? file_handler_poll_drop : nullptr;
auto srna = file_handler_type->rna_ext.srna;
BKE_file_handler_add(std::move(file_handler_type));
return srna;
}
static StructRNA *rna_FileHandler_refine(PointerRNA *file_handler_ptr)
{
FileHandler *file_handler = (FileHandler *)file_handler_ptr->data;
guishe marked this conversation as resolved

Can this parsing be moved into file_handler.cc?

Can this parsing be moved into `file_handler.cc`?
return (file_handler->type && file_handler->type->rna_ext.srna) ?
file_handler->type->rna_ext.srna :
&RNA_FileHandler;
}
#else /* RNA_RUNTIME */
static void rna_def_ui_layout(BlenderRNA *brna)
@ -2198,6 +2315,72 @@ static void rna_def_asset_shelf(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_REGIONS_ASSET_SHELF, nullptr);
}
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,
guishe marked this conversation as resolved Outdated

That description is not really useful, just rewording the struct label.

Better to get a short explanation of what is a file handler here.

That description is not really useful, just rewording the struct label. Better to get a short explanation of what is a file handler here.

As it is currently it will only add drag and drop support, I think this would fit:

Extends functionality to operators that manages files, such as adding drag and drop support.

As it is currently it will only add drag and drop support, I think this would fit: `Extends functionality to operators that manages files, such as adding drag and drop support.`
"File Handler Type",
"Extends functionality to operators that manages files, such as adding "
"drag and drop support");
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(
guishe marked this conversation as resolved
Review

with the extensions given in bl_file_extensions

`with the extensions given in bl_file_extensions`
prop,
"Operator",
"Operator that can handle import files with the extensions given 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",
"Formatted string of file extensions supported by the file handler, each extension should "
"start with a \".\" and be separated by \";\"."
"\nFor Example: `\".blend;.ble\"`");
PropertyRNA *parm;
guishe marked this conversation as resolved
Review

typo: handler

a non-null output -> True

Would also add precision: can be used to handle the drop of a drag-and-drop action. At some point I would expect we add more poll callbacks for other types of file handling.

typo: `handler` `a non-null output` -> `True` Would also add precision: `can be used to handle the drop of a drag-and-drop action`. At some point I would expect we add more poll callbacks for other types of file handling.
FunctionRNA *func;
guishe marked this conversation as resolved
Review

visible is very confusing name here? Also for booleans, we recommend using is_ or use_ prefixes, e.g. here could be is_usable...

See also https://wiki.blender.org/wiki/Source/Architecture/RNA#Defining_Structs_and_Properties

`visible` is very confusing name here? Also for booleans, we recommend using `is_` or `use_` prefixes, e.g. here could be `is_usable`... See also https://wiki.blender.org/wiki/Source/Architecture/RNA#Defining_Structs_and_Properties
func = RNA_def_function(srna, "poll_drop", nullptr);
RNA_def_function_ui_description(
func,
"If this method returns True, can be used to handle the drop of a drag-and-drop action");
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
RNA_def_function_return(func, RNA_def_boolean(func, "is_usable", true, "", ""));
parm = RNA_def_pointer(func, "context", "Context", "", "");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
}
void RNA_def_ui(BlenderRNA *brna)
{
rna_def_ui_layout(brna);
@ -2206,6 +2389,7 @@ void RNA_def_ui(BlenderRNA *brna)
rna_def_header(brna);
rna_def_menu(brna);
rna_def_asset_shelf(brna);
rna_def_file_handler(brna);
}
#endif /* RNA_RUNTIME */

View File

@ -8900,7 +8900,8 @@ PyDoc_STRVAR(pyrna_register_class_doc,
" :class:`bpy.types.Panel`, :class:`bpy.types.UIList`,\n"
" :class:`bpy.types.Menu`, :class:`bpy.types.Header`,\n"
" :class:`bpy.types.Operator`, :class:`bpy.types.KeyingSetInfo`,\n"
" :class:`bpy.types.RenderEngine`, :class:`bpy.types.AssetShelf`\n"
" :class:`bpy.types.RenderEngine`, :class:`bpy.types.AssetShelf`,\n"
" :class:`bpy.types.FileHandler`\n"
" :type cls: class\n"
" :raises ValueError:\n"
" if the class is not a subclass of a registerable blender class.\n"