WIP: Experiment: Drop import operator helper and file drop type #111242
|
@ -3501,9 +3501,9 @@ class WM_OT_drop_blend_file(Operator):
|
|||
|
||||
class WM_FH_alembic(bpy.types.FileHandler):
|
||||
bl_idname = "WM_FH_alembic"
|
||||
bl_label = "alembic"
|
||||
bl_label = "Import Alembic"
|
||||
bl_import_operator = "WM_OT_alembic_import"
|
||||
bl_extensions = [{"name": ".abc"}, {"name": ".abc"}, {"name": ".abc"}]
|
||||
bl_file_extensions = [{"extension": ".abc"}]
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@ -3512,9 +3512,9 @@ class WM_FH_alembic(bpy.types.FileHandler):
|
|||
|
||||
class WM_FH_collada(bpy.types.FileHandler):
|
||||
bl_idname = "WM_FH_collada"
|
||||
bl_label = "collada"
|
||||
bl_label = "Import COLLADA"
|
||||
bl_import_operator = "WM_OT_collada_import"
|
||||
bl_extensions = [{"name": ".dae"}]
|
||||
bl_file_extensions = [{"extension": ".dae"}]
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@ -3523,9 +3523,9 @@ class WM_FH_collada(bpy.types.FileHandler):
|
|||
|
||||
class WM_FH_gpencil(bpy.types.FileHandler):
|
||||
bl_idname = "WM_FH_gpencil"
|
||||
bl_label = "gpencil"
|
||||
bl_label = "Import gpencil"
|
||||
bl_import_operator = "WM_OT_gpencil_import_svg"
|
||||
bl_extensions = [{"name": ".svg"}]
|
||||
bl_file_extensions = [{"extension": ".svg"}]
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@ -3534,9 +3534,9 @@ class WM_FH_gpencil(bpy.types.FileHandler):
|
|||
|
||||
class WM_FH_obj(bpy.types.FileHandler):
|
||||
bl_idname = "WM_FH_obj"
|
||||
bl_label = "obj"
|
||||
bl_label = "Import Wavefront OBJ"
|
||||
bl_import_operator = "WM_OT_obj_import"
|
||||
bl_extensions = [{"name": ".obj"}]
|
||||
bl_file_extensions = [{"extension": ".obj"}]
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@ -3545,9 +3545,9 @@ class WM_FH_obj(bpy.types.FileHandler):
|
|||
|
||||
class WM_FH_ply(bpy.types.FileHandler):
|
||||
bl_idname = "WM_FH_ply"
|
||||
bl_label = "ply"
|
||||
bl_label = "Import PLY"
|
||||
bl_import_operator = "WM_OT_ply_import"
|
||||
bl_extensions = [{"name": ".ply"}]
|
||||
bl_file_extensions = [{"extension": ".ply"}]
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@ -3556,9 +3556,9 @@ class WM_FH_ply(bpy.types.FileHandler):
|
|||
|
||||
class WM_FH_stl(bpy.types.FileHandler):
|
||||
bl_idname = "WM_FH_stl"
|
||||
bl_label = "stl"
|
||||
bl_label = "Import STL (experimental)"
|
||||
bl_import_operator = "WM_OT_stl_import"
|
||||
bl_extensions = [{"name": ".stl"}]
|
||||
bl_file_extensions = [{"extension": ".stl"}]
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@ -3567,9 +3567,9 @@ class WM_FH_stl(bpy.types.FileHandler):
|
|||
|
||||
class WM_FH_import_mesh_stl(bpy.types.FileHandler):
|
||||
bl_idname = "WM_FH_import_mesh_stl"
|
||||
bl_label = "stl"
|
||||
bl_label = "Import STL"
|
||||
bl_import_operator = "import_mesh.stl"
|
||||
bl_extensions = [{"name": ".stl"}]
|
||||
bl_file_extensions = [{"extension": ".stl"}]
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@ -3578,9 +3578,9 @@ class WM_FH_import_mesh_stl(bpy.types.FileHandler):
|
|||
|
||||
class WM_FH_usd(bpy.types.FileHandler):
|
||||
bl_idname = "WM_FH_usd"
|
||||
bl_label = "usd"
|
||||
bl_label = "Import USD"
|
||||
bl_import_operator = "WM_OT_usd_import"
|
||||
bl_extensions = [{"name": ".usd"}]
|
||||
bl_file_extensions = [{"extension": ".usd"}]
|
||||
guishe marked this conversation as resolved
Outdated
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
|
|
@ -668,15 +668,16 @@ struct bFileExtension {
|
|||
};
|
||||
struct FileHandlerType {
|
||||
|
||||
char idname[BKE_ST_MAXNAME]; /* unique name */
|
||||
char idname[BKE_ST_MAXNAME]; /* Unique name. */
|
||||
|
||||
char label[BKE_ST_MAXNAME]; /* label */
|
||||
char label[BKE_ST_MAXNAME]; /* For UI text. */
|
||||
|
||||
char import_operator[BKE_ST_MAXNAME]; /* import operator name */
|
||||
char import_operator[BKE_ST_MAXNAME]; /* Import operator name, same as #OP_MAX_TYPENAME. */
|
||||
|
||||
guishe marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
This should move to its own file, This should move to its own file, `BKE_file_handler.h`
|
||||
/** TODO */
|
||||
/* Check if file handler can be used in a context. */
|
||||
bool (*poll)(const struct bContext *C, FileHandlerType *file_handle_type);
|
||||
guishe marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
Leave empty line between struct definitions. Leave empty line between struct definitions.
|
||||
|
||||
/* List of file extensions supported by the file handler. */
|
||||
blender::Vector<bFileExtension> extensions;
|
||||
|
||||
/** Equivalent to datablocks ID properties. */
|
||||
|
|
|
@ -32,10 +32,10 @@ static bool poll_extension(blender::Span<bFileExtension> file_extensions, const
|
|||
return false;
|
||||
}
|
||||
|
||||
static blender::Vector<wmOperatorType *> poll_operators_for_extension(const bContext *C,
|
||||
const char *extension)
|
||||
static blender::Vector<FileHandlerType *> poll_file_handlers_for_extension(bContext *C,
|
||||
const char *extension)
|
||||
{
|
||||
blender::Vector<wmOperatorType *> operators;
|
||||
blender::Vector<FileHandlerType *> result;
|
||||
for (auto *file_handler : BKE_file_handlers()) {
|
||||
if (!poll_extension(file_handler->extensions, extension)) {
|
||||
continue;
|
||||
|
@ -45,11 +45,12 @@ static blender::Vector<wmOperatorType *> poll_operators_for_extension(const bCon
|
|||
}
|
||||
wmOperatorType *test_operator = WM_operatortype_find(file_handler->import_operator, false);
|
||||
if (!test_operator) {
|
||||
/* Discard if import operator does not exist. */
|
||||
continue;
|
||||
}
|
||||
operators.append(test_operator);
|
||||
result.append(file_handler);
|
||||
}
|
||||
return operators;
|
||||
return result;
|
||||
}
|
||||
|
||||
static PointerRNA copy_file_properties_to_operator_type_pointer(wmOperator *op, wmOperatorType *ot)
|
||||
|
@ -88,13 +89,15 @@ static int wm_drop_import_helper_exec(bContext *C, wmOperator *op)
|
|||
{
|
||||
char extension[MAX_NAME];
|
||||
RNA_string_get(op->ptr, "extension", extension);
|
||||
blender::Vector<wmOperatorType *> operators = poll_operators_for_extension(C, extension);
|
||||
|
||||
if (operators.size() == 0) {
|
||||
blender::Vector<FileHandlerType *> file_handlers = poll_file_handlers_for_extension(C,
|
||||
extension);
|
||||
|
||||
if (file_handlers.size() == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
wmOperatorType *ot = operators[0];
|
||||
wmOperatorType *ot = WM_operatortype_find(file_handlers[0]->import_operator, false);
|
||||
|
||||
PointerRNA op_props = copy_file_properties_to_operator_type_pointer(op, ot);
|
||||
|
||||
|
@ -108,9 +111,10 @@ static int wm_drop_import_helper_invoke(bContext *C, wmOperator *op, const wmEve
|
|||
char extension[MAX_NAME];
|
||||
RNA_string_get(op->ptr, "extension", extension);
|
||||
|
||||
blender::Vector<wmOperatorType *> operators = poll_operators_for_extension(C, extension);
|
||||
blender::Vector<FileHandlerType *> file_handlers = poll_file_handlers_for_extension(C,
|
||||
extension);
|
||||
|
||||
if (operators.size() <= 1) {
|
||||
if (file_handlers.size() == 1) {
|
||||
return wm_drop_import_helper_exec(C, op);
|
||||
}
|
||||
|
||||
|
@ -118,11 +122,12 @@ static int wm_drop_import_helper_invoke(bContext *C, wmOperator *op, const wmEve
|
|||
uiLayout *layout = UI_popup_menu_layout(pup);
|
||||
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
|
||||
|
||||
for (auto *ot : operators) {
|
||||
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);
|
||||
uiItemFullO_ptr(layout,
|
||||
guishe marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
Use Use `IFACE_("Import %s")` for translation.
|
||||
ot,
|
||||
nullptr,
|
||||
file_handler->label,
|
||||
ICON_NONE,
|
||||
static_cast<IDProperty *>(op_props.data),
|
||||
WM_OP_INVOKE_DEFAULT,
|
||||
|
@ -137,8 +142,8 @@ void WM_OT_drop_import_helper(wmOperatorType *ot)
|
|||
{
|
||||
guishe marked this conversation as resolved
Outdated
Brecht Van Lommel
commented
Leave empty line between function definitions. Leave empty line between function definitions.
|
||||
ot->name = "Drop Import Herlper";
|
||||
ot->description =
|
||||
"Helper operator that handles file drops events and calls operators that can import files "
|
||||
"with extension";
|
||||
"Helper operator that handles file drops and uses file handler information to call "
|
||||
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"?
|
||||
"operators that can import a file with extension.";
|
||||
ot->idname = "WM_OT_drop_import_helper";
|
||||
|
||||
ot->exec = wm_drop_import_helper_exec;
|
||||
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.
|
||||
|
@ -187,19 +192,20 @@ static bool poll(bContext *C, wmDrag *drag, const wmEvent * /*event*/)
|
|||
const auto paths = WM_drag_get_paths(drag);
|
||||
const char *extension = BLI_path_extension(paths[0].c_str());
|
||||
|
||||
return extension && poll_operators_for_extension(C, extension).size() > 0;
|
||||
return extension && poll_file_handlers_for_extension(C, extension).size() > 0;
|
||||
}
|
||||
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());
|
||||
|
||||
blender::Vector<wmOperatorType *> operators = poll_operators_for_extension(C, extension);
|
||||
if (operators.size() == 0) {
|
||||
blender::Vector<FileHandlerType *> file_handlers = poll_file_handlers_for_extension(C,
|
||||
extension);
|
||||
if (file_handlers.size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
if (operators.size() == 1) {
|
||||
return BLI_strdup(operators[0]->name ? operators[0]->name : operators[0]->idname);
|
||||
if (file_handlers.size() == 1) {
|
||||
return BLI_strdup(file_handlers[0]->label);
|
||||
}
|
||||
|
||||
return BLI_strdup("Multiple operators can handle this file(s), drop to pick which to use");
|
||||
|
|
|
@ -1371,20 +1371,22 @@ static StructRNA *rna_FileHandler_register(Main *bmain,
|
|||
file_handler_type->id_properties = dummy_file_handler_type.id_properties;
|
||||
file_handler_type->rna_ext = dummy_file_handler_type.rna_ext;
|
||||
memcpy(&file_handler_type->rna_ext, &dummy_file_handler_type.rna_ext, sizeof(ExtensionRNA));
|
||||
int extensions_len = RNA_collection_length(&dummy_file_handler_ptr, "bl_extensions");
|
||||
PropertyRNA *prop = RNA_struct_find_property(&dummy_file_handler_ptr, "bl_extensions");
|
||||
|
||||
/* Load all file extensions defined in the IDProperty. */
|
||||
int extensions_len = RNA_collection_length(&dummy_file_handler_ptr, "bl_file_extensions");
|
||||
PropertyRNA *prop = RNA_struct_find_property(&dummy_file_handler_ptr, "bl_file_extensions");
|
||||
|
||||
for (int i = 0; i < extensions_len; i++) {
|
||||
PointerRNA fileptr;
|
||||
bFileExtension extension;
|
||||
|
||||
RNA_property_collection_lookup_int(&dummy_file_handler_ptr, prop, i, &fileptr);
|
||||
RNA_string_get(&fileptr, "name", extension.extension);
|
||||
|
||||
RNA_string_get(&fileptr, "extension", extension.extension);
|
||||
|
||||
file_handler_type->extensions.append(extension);
|
||||
}
|
||||
|
||||
RNA_collection_clear(&dummy_file_handler_ptr, "bl_extensions");
|
||||
RNA_collection_clear(&dummy_file_handler_ptr, "bl_file_extensions");
|
||||
|
||||
file_handler_type->rna_ext.srna = RNA_def_struct_ptr(
|
||||
&BLENDER_RNA, file_handler_type->idname, &RNA_FileHandler);
|
||||
|
@ -2228,7 +2230,7 @@ static void rna_def_file_handler_extensions(BlenderRNA *brna, PropertyRNA *cprop
|
|||
RNA_def_property_srna(cprop, "FileExtensions");
|
||||
srna = RNA_def_struct(brna, "FileExtensions", nullptr);
|
||||
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.
|
||||
RNA_def_struct_sdna(srna, "bFileExtension");
|
||||
RNA_def_struct_ui_text(srna, "File Extensions", "TODO");
|
||||
RNA_def_struct_ui_text(srna, "File Extensions", "File extensions for file handlers");
|
||||
}
|
||||
|
||||
static void rna_def_file_handler(BlenderRNA *brna)
|
||||
|
@ -2237,16 +2239,17 @@ static void rna_def_file_handler(BlenderRNA *brna)
|
|||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "FileHandler", nullptr);
|
||||
RNA_def_struct_ui_text(srna, "File Handler Type", "TODO");
|
||||
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_idprops_func(srna, "rna_FileHandler_idprops");
|
||||
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 */
|
||||
|
||||
RNA_define_verify_sdna(true); /* 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);
|
||||
|
@ -2260,24 +2263,28 @@ static void rna_def_file_handler(BlenderRNA *brna)
|
|||
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);
|
||||
RNA_def_property_ui_text(prop, "Operator", "TODO");
|
||||
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", "TODO");
|
||||
RNA_def_property_ui_text(prop, "Label", "The file handler label");
|
||||
|
||||
prop = RNA_def_property(srna, "bl_extensions", PROP_COLLECTION, PROP_NONE);
|
||||
prop = RNA_def_property(srna, "bl_file_extensions", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_REGISTER | PROP_IDPROPERTY);
|
||||
RNA_def_property_struct_type(prop, "FileExtension");
|
||||
RNA_def_property_ui_text(prop, "Extensions", "TODO");
|
||||
RNA_def_property_ui_text(prop, "File Extensions", "List of file extensions supported");
|
||||
rna_def_file_handler_extensions(brna, prop);
|
||||
|
||||
PropertyRNA *parm;
|
||||
FunctionRNA *func;
|
||||
|
||||
func = RNA_def_function(srna, "poll", nullptr);
|
||||
RNA_def_function_ui_description(func, "TODO");
|
||||
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", "", "");
|
||||
|
@ -2391,12 +2398,12 @@ static void rna_def_file_extension(BlenderRNA *brna)
|
|||
PropertyRNA *prop;
|
||||
srna = RNA_def_struct(brna, "FileExtension", nullptr);
|
||||
RNA_def_struct_sdna(srna, "bFileExtension");
|
||||
RNA_def_struct_ui_text(srna, "File Extension", "TODO");
|
||||
RNA_def_struct_ui_text(srna, "File Extension", "File extension for file handlers");
|
||||
|
||||
RNA_define_verify_sdna(false);
|
||||
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_define_verify_sdna(false); /* not in sdna */
|
||||
prop = RNA_def_property(srna, "extension", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, nullptr, "extension");
|
||||
RNA_def_property_ui_text(prop, "Extension", "TODO");
|
||||
RNA_def_property_ui_text(prop, "Extension", "File extension");
|
||||
RNA_define_verify_sdna(true);
|
||||
}
|
||||
void RNA_def_ui(BlenderRNA *brna)
|
||||
|
|
There is also
usda
,usdc
,usdz
.