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:
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
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ struct OBJImportParams {
|
|||
bool import_vertex_groups;
|
||||
bool validate_meshes;
|
||||
bool relative_paths;
|
||||
bool clear_selection;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue