obj: support importing multiple files at once

Implemented the same way as STL or GPencil SVG importers: loop over
the input files, import one by one.

Has been requested by the community for quite a long time
(e.g. https://blender.community/c/rightclickselect/Jhbbbc/), as well
as 3rd party addons to implement just this
(https://github.com/p2or/blender-batch-import-wavefront-obj).
This commit is contained in:
Aras Pranckevicius 2022-08-11 17:05:54 +03:00
parent c4a0438522
commit 4cbd799373
Notes: blender-bot 2023-02-14 08:35:51 +01:00
Referenced by issue #100749, Blender LTS: Maintenance Task 3.3
5 changed files with 50 additions and 10 deletions

View File

@ -382,11 +382,6 @@ static int wm_obj_import_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
static int wm_obj_import_exec(bContext *C, wmOperator *op)
{
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
BKE_report(op->reports, RPT_ERROR, "No filename given");
return OPERATOR_CANCELLED;
}
struct OBJImportParams import_params;
RNA_string_get(op->ptr, "filepath", import_params.filepath);
import_params.clamp_size = RNA_float_get(op->ptr, "clamp_size");
@ -395,8 +390,35 @@ static int wm_obj_import_exec(bContext *C, wmOperator *op)
import_params.import_vertex_groups = RNA_boolean_get(op->ptr, "import_vertex_groups");
import_params.validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes");
import_params.relative_paths = ((U.flag & USER_RELPATHS) != 0);
import_params.clear_selection = true;
OBJ_import(C, &import_params);
int files_len = RNA_collection_length(op->ptr, "files");
if (files_len) {
/* Importing multiple files: loop over them and import one by one. */
PointerRNA fileptr;
PropertyRNA *prop;
char dir_only[FILE_MAX], file_only[FILE_MAX];
RNA_string_get(op->ptr, "directory", dir_only);
prop = RNA_struct_find_property(op->ptr, "files");
for (int i = 0; i < files_len; i++) {
RNA_property_collection_lookup_int(op->ptr, prop, i, &fileptr);
RNA_string_get(&fileptr, "name", file_only);
BLI_join_dirfile(
import_params.filepath, sizeof(import_params.filepath), dir_only, file_only);
import_params.clear_selection = (i == 0);
OBJ_import(C, &import_params);
}
}
else if (RNA_struct_property_is_set(op->ptr, "filepath")) {
/* Importing one file. */
RNA_string_get(op->ptr, "filepath", import_params.filepath);
OBJ_import(C, &import_params);
}
else {
BKE_report(op->reports, RPT_ERROR, "No filename given");
return OPERATOR_CANCELLED;
}
Scene *scene = CTX_data_scene(C);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@ -454,7 +476,8 @@ void WM_OT_obj_import(struct wmOperatorType *ot)
FILE_TYPE_FOLDER,
FILE_BLENDER,
FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS,
WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS |
WM_FILESEL_DIRECTORY | WM_FILESEL_FILES,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
RNA_def_float(

View File

@ -4,6 +4,7 @@
* \ingroup obj
*/
#include "BLI_path_util.h"
#include "BLI_timeit.hh"
#include "IO_wavefront_obj.h"
@ -11,14 +12,26 @@
#include "obj_exporter.hh"
#include "obj_importer.hh"
using namespace blender::timeit;
static void report_duration(const char *job, const TimePoint &start_time, const char *path)
{
Nanoseconds duration = Clock::now() - start_time;
std::cout << "OBJ " << job << " of '" << BLI_path_basename(path) << "' took ";
print_duration(duration);
std::cout << '\n';
}
void OBJ_export(bContext *C, const OBJExportParams *export_params)
{
SCOPED_TIMER("OBJ export");
TimePoint start_time = Clock::now();
blender::io::obj::exporter_main(C, *export_params);
report_duration("export", start_time, export_params->filepath);
}
void OBJ_import(bContext *C, const OBJImportParams *import_params)
{
SCOPED_TIMER(__func__);
TimePoint start_time = Clock::now();
blender::io::obj::importer_main(C, *import_params);
report_duration("import", start_time, import_params->filepath);
}

View File

@ -75,6 +75,7 @@ struct OBJImportParams {
bool import_vertex_groups;
bool validate_meshes;
bool relative_paths;
bool clear_selection;
};
/**

View File

@ -39,7 +39,6 @@ static void geometry_to_blender_objects(Main *bmain,
Map<std::string, std::unique_ptr<MTLMaterial>> &materials,
Map<std::string, Material *> &created_materials)
{
BKE_view_layer_base_deselect_all(view_layer);
LayerCollection *lc = BKE_layer_collection_get_active(view_layer);
/* Don't do collection syncs for each object, will do once after the loop. */
@ -122,6 +121,9 @@ void importer_main(Main *bmain,
mtl_parser.parse_and_store(materials);
}
if (import_params.clear_selection) {
BKE_view_layer_base_deselect_all(view_layer);
}
geometry_to_blender_objects(bmain,
scene,
view_layer,

View File

@ -62,6 +62,7 @@ class obj_importer_test : public BlendfileLoadingBaseTest {
params.validate_meshes = true;
params.import_vertex_groups = false;
params.relative_paths = true;
params.clear_selection = true;
std::string obj_path = blender::tests::flags_test_asset_dir() + "/io_tests/obj/" + path;
strncpy(params.filepath, obj_path.c_str(), FILE_MAX - 1);