Blender V5.0
io_obj.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#ifdef WITH_IO_WAVEFRONT_OBJ
10
11# include "DNA_space_types.h"
12
13# include "BKE_context.hh"
14# include "BKE_file_handler.hh"
15# include "BKE_main.hh"
16# include "BKE_report.hh"
17
18# include "BLI_path_utils.hh"
19# include "BLI_string.h"
20# include "BLI_string_utf8.h"
21
22# include "BLT_translation.hh"
23
24# include "ED_fileselect.hh"
25# include "ED_outliner.hh"
26
27# include "RNA_access.hh"
28# include "RNA_define.hh"
29
30# include "UI_interface.hh"
31# include "UI_interface_layout.hh"
32# include "UI_resources.hh"
33
34# include "WM_api.hh"
35# include "WM_types.hh"
36
37# include "DEG_depsgraph.hh"
38
39# include "IO_orientation.hh"
40# include "IO_path_util_types.hh"
41# include "IO_wavefront_obj.hh"
42
43# include "io_obj.hh"
44# include "io_utils.hh"
45
46static const EnumPropertyItem io_obj_export_evaluation_mode[] = {
47 {DAG_EVAL_RENDER, "DAG_EVAL_RENDER", 0, "Render", "Export objects as they appear in render"},
49 "DAG_EVAL_VIEWPORT",
50 0,
51 "Viewport",
52 "Export objects as they appear in the viewport"},
53 {0, nullptr, 0, nullptr, nullptr}};
54
55static const EnumPropertyItem io_obj_path_mode[] = {
56 {PATH_REFERENCE_AUTO, "AUTO", 0, "Auto", "Use relative paths with subdirectories only"},
57 {PATH_REFERENCE_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Always write absolute paths"},
58 {PATH_REFERENCE_RELATIVE, "RELATIVE", 0, "Relative", "Write relative paths where possible"},
59 {PATH_REFERENCE_MATCH, "MATCH", 0, "Match", "Match absolute/relative setting with input path"},
60 {PATH_REFERENCE_STRIP, "STRIP", 0, "Strip", "Write filename only"},
61 {PATH_REFERENCE_COPY, "COPY", 0, "Copy", "Copy the file to the destination path"},
62 {0, nullptr, 0, nullptr, nullptr}};
63
64static const EnumPropertyItem io_obj_mtl_name_collision_mode[] = {
66 "MAKE_UNIQUE",
67 0,
68 "Make Unique",
69 "Create new materials with unique names for each OBJ file"},
71 "REFERENCE_EXISTING",
72 0,
73 "Reference Existing",
74 "Use existing materials with same name instead of creating new ones"},
75 {0, nullptr, 0, nullptr, nullptr}};
76
77static wmOperatorStatus wm_obj_export_invoke(bContext *C,
78 wmOperator *op,
79 const wmEvent * /*event*/)
80{
82
85}
86
87static wmOperatorStatus wm_obj_export_exec(bContext *C, wmOperator *op)
88{
89 if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
90 BKE_report(op->reports, RPT_ERROR, "No filepath given");
91 return OPERATOR_CANCELLED;
92 }
93 OBJExportParams export_params;
94 export_params.file_base_for_tests[0] = '\0';
95 RNA_string_get(op->ptr, "filepath", export_params.filepath);
96 export_params.blen_filepath = CTX_data_main(C)->filepath;
97 export_params.export_animation = RNA_boolean_get(op->ptr, "export_animation");
98 export_params.start_frame = RNA_int_get(op->ptr, "start_frame");
99 export_params.end_frame = RNA_int_get(op->ptr, "end_frame");
100
101 export_params.forward_axis = eIOAxis(RNA_enum_get(op->ptr, "forward_axis"));
102 export_params.up_axis = eIOAxis(RNA_enum_get(op->ptr, "up_axis"));
103 export_params.global_scale = RNA_float_get(op->ptr, "global_scale");
104 export_params.apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers");
105 export_params.apply_transform = RNA_boolean_get(op->ptr, "apply_transform");
106 export_params.export_eval_mode = eEvaluationMode(RNA_enum_get(op->ptr, "export_eval_mode"));
107
108 export_params.export_selected_objects = RNA_boolean_get(op->ptr, "export_selected_objects");
109 export_params.export_uv = RNA_boolean_get(op->ptr, "export_uv");
110 export_params.export_normals = RNA_boolean_get(op->ptr, "export_normals");
111 export_params.export_colors = RNA_boolean_get(op->ptr, "export_colors");
112 export_params.export_materials = RNA_boolean_get(op->ptr, "export_materials");
113 export_params.path_mode = ePathReferenceMode(RNA_enum_get(op->ptr, "path_mode"));
114 export_params.export_triangulated_mesh = RNA_boolean_get(op->ptr, "export_triangulated_mesh");
115 export_params.export_curves_as_nurbs = RNA_boolean_get(op->ptr, "export_curves_as_nurbs");
116 export_params.export_pbr_extensions = RNA_boolean_get(op->ptr, "export_pbr_extensions");
117
118 export_params.export_object_groups = RNA_boolean_get(op->ptr, "export_object_groups");
119 export_params.export_material_groups = RNA_boolean_get(op->ptr, "export_material_groups");
120 export_params.export_vertex_groups = RNA_boolean_get(op->ptr, "export_vertex_groups");
121 export_params.export_smooth_groups = RNA_boolean_get(op->ptr, "export_smooth_groups");
122 export_params.smooth_groups_bitflags = RNA_boolean_get(op->ptr, "smooth_group_bitflags");
123
124 export_params.reports = op->reports;
125
126 RNA_string_get(op->ptr, "collection", export_params.collection);
127
128 OBJ_export(C, &export_params);
129
131 return OPERATOR_CANCELLED;
132 }
133
134 BKE_report(op->reports, RPT_INFO, "File exported successfully");
135 return OPERATOR_FINISHED;
136}
137
138static void ui_obj_export_settings(const bContext *C, uiLayout *layout, PointerRNA *ptr)
139{
140 const bool export_animation = RNA_boolean_get(ptr, "export_animation");
141 const bool export_smooth_groups = RNA_boolean_get(ptr, "export_smooth_groups");
142 const bool export_materials = RNA_boolean_get(ptr, "export_materials");
143
144 layout->use_property_split_set(true);
145 layout->use_property_decorate_set(false);
146
147 /* Object General options. */
148 if (uiLayout *panel = layout->panel(C, "OBJ_export_general", false, IFACE_("General"))) {
149 uiLayout *col = &panel->column(false);
150
151 if (CTX_wm_space_file(C)) {
152 uiLayout *sub = &col->column(false, IFACE_("Include"));
153 sub->prop(ptr, "export_selected_objects", UI_ITEM_NONE, IFACE_("Selection Only"), ICON_NONE);
154 }
155
156 col->prop(ptr, "global_scale", UI_ITEM_NONE, std::nullopt, ICON_NONE);
157 col->prop(ptr, "forward_axis", UI_ITEM_NONE, IFACE_("Forward Axis"), ICON_NONE);
158 col->prop(ptr, "up_axis", UI_ITEM_NONE, IFACE_("Up Axis"), ICON_NONE);
159 }
160
161 /* Geometry options. */
162 if (uiLayout *panel = layout->panel(C, "OBJ_export_geometry", false, IFACE_("Geometry"))) {
163 uiLayout *col = &panel->column(false);
164 col->prop(ptr, "export_uv", UI_ITEM_NONE, IFACE_("UV Coordinates"), ICON_NONE);
165 col->prop(ptr, "export_normals", UI_ITEM_NONE, IFACE_("Normals"), ICON_NONE);
166 col->prop(ptr, "export_colors", UI_ITEM_NONE, IFACE_("Colors"), ICON_NONE);
167 col->prop(ptr, "export_curves_as_nurbs", UI_ITEM_NONE, IFACE_("Curves as NURBS"), ICON_NONE);
168
169 col->prop(
170 ptr, "export_triangulated_mesh", UI_ITEM_NONE, IFACE_("Triangulated Mesh"), ICON_NONE);
171 col->prop(ptr, "apply_modifiers", UI_ITEM_NONE, IFACE_("Apply Modifiers"), ICON_NONE);
172 col->prop(ptr, "apply_transform", UI_ITEM_NONE, IFACE_("Apply Transform"), ICON_NONE);
173 col->prop(ptr, "export_eval_mode", UI_ITEM_NONE, IFACE_("Properties"), ICON_NONE);
174 }
175
176 /* Grouping options. */
177 if (uiLayout *panel = layout->panel(C, "OBJ_export_grouping", false, IFACE_("Grouping"))) {
178 uiLayout *col = &panel->column(false);
179 col->prop(ptr, "export_object_groups", UI_ITEM_NONE, IFACE_("Object Groups"), ICON_NONE);
180 col->prop(ptr, "export_material_groups", UI_ITEM_NONE, IFACE_("Material Groups"), ICON_NONE);
181 col->prop(ptr, "export_vertex_groups", UI_ITEM_NONE, IFACE_("Vertex Groups"), ICON_NONE);
182 col->prop(ptr, "export_smooth_groups", UI_ITEM_NONE, IFACE_("Smooth Groups"), ICON_NONE);
183 col = &col->column(false);
184 col->enabled_set(export_smooth_groups);
185 col->prop(
186 ptr, "smooth_group_bitflags", UI_ITEM_NONE, IFACE_("Smooth Group Bitflags"), ICON_NONE);
187 }
188
189 /* Material options. */
190 PanelLayout panel = layout->panel(C, "OBJ_export_materials", false);
191 panel.header->use_property_split_set(false);
192 panel.header->prop(ptr, "export_materials", UI_ITEM_NONE, "", ICON_NONE);
193 panel.header->label(IFACE_("Materials"), ICON_NONE);
194 if (panel.body) {
195 uiLayout *col = &panel.body->column(false);
196 col->enabled_set(export_materials);
197
198 col->prop(ptr, "export_pbr_extensions", UI_ITEM_NONE, IFACE_("PBR Extensions"), ICON_NONE);
199 col->prop(ptr, "path_mode", UI_ITEM_NONE, IFACE_("Path Mode"), ICON_NONE);
200 }
201
202 /* Animation options. */
203 panel = layout->panel(C, "OBJ_export_animation", true);
204 panel.header->use_property_split_set(false);
205 panel.header->prop(ptr, "export_animation", UI_ITEM_NONE, "", ICON_NONE);
206 panel.header->label(IFACE_("Animation"), ICON_NONE);
207 if (panel.body) {
208 uiLayout *col = &panel.body->column(false);
209 col->enabled_set(export_animation);
210
211 col->prop(ptr, "start_frame", UI_ITEM_NONE, IFACE_("Frame Start"), ICON_NONE);
212 col->prop(ptr, "end_frame", UI_ITEM_NONE, IFACE_("End"), ICON_NONE);
213 }
214}
215
216static void wm_obj_export_draw(bContext *C, wmOperator *op)
217{
218 ui_obj_export_settings(C, op->layout, op->ptr);
219}
220
224static bool wm_obj_export_check(bContext *C, wmOperator *op)
225{
226 char filepath[FILE_MAX];
227 Scene *scene = CTX_data_scene(C);
228 bool changed = false;
229 RNA_string_get(op->ptr, "filepath", filepath);
230
231 if (!BLI_path_extension_check(filepath, ".obj")) {
232 BLI_path_extension_ensure(filepath, FILE_MAX, ".obj");
233 RNA_string_set(op->ptr, "filepath", filepath);
234 changed = true;
235 }
236
237 {
238 int start = RNA_int_get(op->ptr, "start_frame");
239 int end = RNA_int_get(op->ptr, "end_frame");
240 /* Set the defaults. */
241 if (start == INT_MIN) {
242 start = scene->r.sfra;
243 changed = true;
244 }
245 if (end == INT_MAX) {
246 end = scene->r.efra;
247 changed = true;
248 }
249 /* Fix user errors. */
250 if (end < start) {
251 end = start;
252 changed = true;
253 }
254 RNA_int_set(op->ptr, "start_frame", start);
255 RNA_int_set(op->ptr, "end_frame", end);
256 }
257 return changed;
258}
259
261{
262 PropertyRNA *prop;
263
264 ot->name = "Export Wavefront OBJ";
265 ot->description = "Save the scene to a Wavefront OBJ file";
266 ot->idname = "WM_OT_obj_export";
267
268 ot->invoke = wm_obj_export_invoke;
269 ot->exec = wm_obj_export_exec;
271 ot->ui = wm_obj_export_draw;
272 ot->check = wm_obj_export_check;
273
274 ot->flag = OPTYPE_PRESET;
275
279 FILE_SAVE,
283
284 /* Animation options. */
285 RNA_def_boolean(ot->srna,
286 "export_animation",
287 false,
288 "Export Animation",
289 "Export multiple frames instead of the current frame only");
290 RNA_def_int(ot->srna,
291 "start_frame",
292 INT_MIN, /* wm_obj_export_check uses this to set scene->r.sfra. */
293 INT_MIN,
294 INT_MAX,
295 "Start Frame",
296 "The first frame to be exported",
297 INT_MIN,
298 INT_MAX);
299 RNA_def_int(ot->srna,
300 "end_frame",
301 INT_MAX, /* wm_obj_export_check uses this to set scene->r.efra. */
302 INT_MIN,
303 INT_MAX,
304 "End Frame",
305 "The last frame to be exported",
306 INT_MIN,
307 INT_MAX);
308 /* Object transform options. */
309 prop = RNA_def_enum(
310 ot->srna, "forward_axis", io_transform_axis, IO_AXIS_NEGATIVE_Z, "Forward Axis", "");
312 prop = RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Y, "Up Axis", "");
315 ot->srna,
316 "global_scale",
317 1.0f,
318 0.0001f,
319 10000.0f,
320 "Scale",
321 "Value by which to enlarge or shrink the objects with respect to the world's origin",
322 0.0001f,
323 10000.0f);
324 /* File Writer options. */
326 ot->srna, "apply_modifiers", true, "Apply Modifiers", "Apply modifiers to exported meshes");
327 RNA_def_boolean(ot->srna,
328 "apply_transform",
329 true,
330 "Apply Transform",
331 "Apply object transforms to exported vertices");
332 RNA_def_enum(ot->srna,
333 "export_eval_mode",
334 io_obj_export_evaluation_mode,
336 "Object Properties",
337 "Determines properties like object visibility, modifiers etc., where they differ "
338 "for Render and Viewport");
339 RNA_def_boolean(ot->srna,
340 "export_selected_objects",
341 false,
342 "Export Selected Objects",
343 "Export only selected objects instead of all supported objects");
344 RNA_def_boolean(ot->srna, "export_uv", true, "Export UVs", "");
345 RNA_def_boolean(ot->srna,
346 "export_normals",
347 true,
348 "Export Normals",
349 "Export per-face normals if the face is flat-shaded, per-face-corner "
350 "normals if smooth-shaded");
351 RNA_def_boolean(ot->srna, "export_colors", false, "Export Colors", "Export per-vertex colors");
352 RNA_def_boolean(ot->srna,
353 "export_materials",
354 true,
355 "Export Materials",
356 "Export MTL library. There must be a Principled-BSDF node for image textures to "
357 "be exported to the MTL file");
358 RNA_def_boolean(ot->srna,
359 "export_pbr_extensions",
360 false,
361 "Export Materials with PBR Extensions",
362 "Export MTL library using PBR extensions (roughness, metallic, sheen, "
363 "coat, anisotropy, transmission)");
364 prop = RNA_def_enum(ot->srna,
365 "path_mode",
366 io_obj_path_mode,
368 "Path Mode",
369 "Method used to reference paths");
371 RNA_def_boolean(ot->srna,
372 "export_triangulated_mesh",
373 false,
374 "Export Triangulated Mesh",
375 "All ngons with four or more vertices will be triangulated. Meshes in "
376 "the scene will not be affected. Behaves like Triangulate Modifier with "
377 "ngon-method: \"Beauty\", quad-method: \"Shortest Diagonal\", min vertices: 4");
378 RNA_def_boolean(ot->srna,
379 "export_curves_as_nurbs",
380 false,
381 "Export Curves as NURBS",
382 "Export curves in parametric form instead of exporting as mesh");
383
384 RNA_def_boolean(ot->srna,
385 "export_object_groups",
386 false,
387 "Export Object Groups",
388 "Append mesh name to object name, separated by a '_'");
389 RNA_def_boolean(ot->srna,
390 "export_material_groups",
391 false,
392 "Export Material Groups",
393 "Generate an OBJ group for each part of a geometry using a different material");
395 ot->srna,
396 "export_vertex_groups",
397 false,
398 "Export Vertex Groups",
399 "Export the name of the vertex group of a face. It is approximated "
400 "by choosing the vertex group with the most members among the vertices of a face");
401 RNA_def_boolean(ot->srna,
402 "export_smooth_groups",
403 false,
404 "Export Smooth Groups",
405 "Generate smooth groups identifiers for each group of smooth faces, as "
406 "unique integer values by default");
408 ot->srna,
409 "smooth_group_bitflags",
410 false,
411 "Bitflags Smooth Groups",
412 "If exporting smoothgroups, generate 'bitflags' values for the groups, instead of "
413 "unique integer values. The same bitflag value can be re-used for different groups of "
414 "smooth faces, as long as they have no common sharp edges or vertices");
415
416 /* Only show `.obj` or `.mtl` files by default. */
417 prop = RNA_def_string(ot->srna, "filter_glob", "*.obj;*.mtl", 0, "Extension Filter", "");
419
420 prop = RNA_def_string(ot->srna, "collection", nullptr, MAX_ID_NAME - 2, "Collection", nullptr);
422}
423
424static wmOperatorStatus wm_obj_import_exec(bContext *C, wmOperator *op)
425{
426 OBJImportParams import_params;
427 import_params.global_scale = RNA_float_get(op->ptr, "global_scale");
428 import_params.clamp_size = RNA_float_get(op->ptr, "clamp_size");
429 import_params.forward_axis = eIOAxis(RNA_enum_get(op->ptr, "forward_axis"));
430 import_params.up_axis = eIOAxis(RNA_enum_get(op->ptr, "up_axis"));
431 import_params.use_split_objects = RNA_boolean_get(op->ptr, "use_split_objects");
432 import_params.use_split_groups = RNA_boolean_get(op->ptr, "use_split_groups");
433 import_params.import_vertex_groups = RNA_boolean_get(op->ptr, "import_vertex_groups");
434 import_params.validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes");
435 import_params.close_spline_loops = RNA_boolean_get(op->ptr, "close_spline_loops");
436 char separator[2] = {};
437 RNA_string_get(op->ptr, "collection_separator", separator);
438 import_params.collection_separator = separator[0];
439 import_params.relative_paths = ((U.flag & USER_RELPATHS) != 0);
440 import_params.clear_selection = true;
442 RNA_enum_get(op->ptr, "mtl_name_collision_mode"));
443
444 import_params.reports = op->reports;
445
447
448 if (paths.is_empty()) {
449 BKE_report(op->reports, RPT_ERROR, "No filepath given");
450 return OPERATOR_CANCELLED;
451 }
452 for (const auto &path : paths) {
453 STRNCPY(import_params.filepath, path.c_str());
454 OBJ_import(C, &import_params);
455 /* Only first import clears selection. */
456 import_params.clear_selection = false;
457 };
458
459 Scene *scene = CTX_data_scene(C);
464
465 return OPERATOR_FINISHED;
466}
467
468static void ui_obj_import_settings(const bContext *C, uiLayout *layout, PointerRNA *ptr)
469{
470 layout->use_property_split_set(true);
471 layout->use_property_decorate_set(false);
472
473 if (uiLayout *panel = layout->panel(C, "OBJ_import_general", false, IFACE_("General"))) {
474 uiLayout *col = &panel->column(false);
475 col->prop(ptr, "global_scale", UI_ITEM_NONE, std::nullopt, ICON_NONE);
476 col->prop(ptr, "clamp_size", UI_ITEM_NONE, std::nullopt, ICON_NONE);
477 col->prop(ptr, "forward_axis", UI_ITEM_NONE, IFACE_("Forward Axis"), ICON_NONE);
478 col->prop(ptr, "up_axis", UI_ITEM_NONE, IFACE_("Up Axis"), ICON_NONE);
479 }
480
481 if (uiLayout *panel = layout->panel(C, "OBJ_import_options", false, IFACE_("Options"))) {
482 uiLayout *col = &panel->column(false);
483 col->prop(ptr, "use_split_objects", UI_ITEM_NONE, std::nullopt, ICON_NONE);
484 col->prop(ptr, "use_split_groups", UI_ITEM_NONE, std::nullopt, ICON_NONE);
485 col->prop(ptr, "import_vertex_groups", UI_ITEM_NONE, std::nullopt, ICON_NONE);
486 col->prop(ptr, "validate_meshes", UI_ITEM_NONE, std::nullopt, ICON_NONE);
487 col->prop(ptr, "close_spline_loops", UI_ITEM_NONE, std::nullopt, ICON_NONE);
488 col->prop(ptr, "collection_separator", UI_ITEM_NONE, std::nullopt, ICON_NONE);
489 }
490
491 if (uiLayout *panel = layout->panel(C, "OBJ_import_materials", false, IFACE_("Materials"))) {
492 uiLayout *col = &panel->column(false);
493 col->prop(ptr, "mtl_name_collision_mode", UI_ITEM_NONE, IFACE_("Name Collision"), ICON_NONE);
494 }
495}
496
497static void wm_obj_import_draw(bContext *C, wmOperator *op)
498{
499 ui_obj_import_settings(C, op->layout, op->ptr);
500}
501
503{
504 PropertyRNA *prop;
505
506 ot->name = "Import Wavefront OBJ";
507 ot->description = "Load a Wavefront OBJ scene";
508 ot->idname = "WM_OT_obj_import";
509 ot->flag = OPTYPE_UNDO | OPTYPE_PRESET;
510
512 ot->exec = wm_obj_import_exec;
514 ot->ui = wm_obj_import_draw;
515
524
526 ot->srna,
527 "global_scale",
528 1.0f,
529 0.0001f,
530 10000.0f,
531 "Scale",
532 "Value by which to enlarge or shrink the objects with respect to the world's origin",
533 0.0001f,
534 10000.0f);
536 ot->srna,
537 "clamp_size",
538 0.0f,
539 0.0f,
540 1000.0f,
541 "Clamp Bounding Box",
542 "Resize the objects to keep bounding box under this value. Value 0 disables clamping",
543 0.0f,
544 1000.0f);
545 prop = RNA_def_enum(
546 ot->srna, "forward_axis", io_transform_axis, IO_AXIS_NEGATIVE_Z, "Forward Axis", "");
548 prop = RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Y, "Up Axis", "");
550 RNA_def_boolean(ot->srna,
551 "use_split_objects",
552 true,
553 "Split By Object",
554 "Import each OBJ 'o' as a separate object");
555 RNA_def_boolean(ot->srna,
556 "use_split_groups",
557 false,
558 "Split By Group",
559 "Import each OBJ 'g' as a separate object");
560 RNA_def_boolean(ot->srna,
561 "import_vertex_groups",
562 false,
563 "Vertex Groups",
564 "Import OBJ groups as vertex groups");
566 ot->srna,
567 "validate_meshes",
568 true,
569 "Validate Meshes",
570 "Ensure the data is valid "
571 "(when disabled, data may be imported which causes crashes displaying or editing)");
572 RNA_def_boolean(ot->srna,
573 "close_spline_loops",
574 true,
575 "Detect Cyclic Curves",
576 "Join curve endpoints if overlapping control points are detected "
577 "(if disabled, no curves will be cyclic)");
578
579 RNA_def_string(ot->srna,
580 "collection_separator",
581 nullptr,
582 2,
583 "Path Separator",
584 "Character used to separate objects name into hierarchical structure");
585
586 /* Material options */
587 RNA_def_enum(ot->srna,
588 "mtl_name_collision_mode",
589 io_obj_mtl_name_collision_mode,
591 "Material Name Collision",
592 "How to handle naming collisions when importing materials");
593
594 /* Only show `.obj` or `.mtl` files by default. */
595 prop = RNA_def_string(ot->srna, "filter_glob", "*.obj;*.mtl", 0, "Extension Filter", "");
597}
598
599namespace blender::ed::io {
601{
602 auto fh = std::make_unique<blender::bke::FileHandlerType>();
603 STRNCPY_UTF8(fh->idname, "IO_FH_obj");
604 STRNCPY_UTF8(fh->import_operator, "WM_OT_obj_import");
605 STRNCPY_UTF8(fh->export_operator, "WM_OT_obj_export");
606 STRNCPY_UTF8(fh->label, "Wavefront OBJ");
607 STRNCPY_UTF8(fh->file_extensions_str, ".obj");
608 fh->poll_drop = poll_file_object_drop;
609 bke::file_handler_add(std::move(fh));
610}
611} // namespace blender::ed::io
612
613#endif /* WITH_IO_WAVEFRONT_OBJ */
SpaceFile * CTX_wm_space_file(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
bool BKE_reports_contain(ReportList *reports, eReportType level)
Definition report.cc:383
@ RPT_INFO
Definition BKE_report.hh:35
@ RPT_ERROR
Definition BKE_report.hh:39
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
#define FILE_MAX
bool BLI_path_extension_check(const char *path, const char *ext) ATTR_NONNULL(1
bool BLI_path_extension_ensure(char *path, size_t path_maxncpy, const char *ext) ATTR_NONNULL(1
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
#define STRNCPY_UTF8(dst, src)
#define IFACE_(msgid)
#define BLT_I18NCONTEXT_EDITOR_FILEBROWSER
eEvaluationMode
@ DAG_EVAL_RENDER
@ DAG_EVAL_VIEWPORT
#define MAX_ID_NAME
Definition DNA_ID.h:373
@ FILE_SORT_DEFAULT
@ FILE_BLENDER
@ FILE_TYPE_FOLDER
@ FILE_DEFAULTDISPLAY
@ USER_RELPATHS
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
void ED_fileselect_ensure_default_filepath(bContext *C, wmOperator *op, const char *extension)
Definition filesel.cc:1470
void ED_outliner_select_sync_from_object_tag(bContext *C)
eIOAxis
@ IO_AXIS_Y
@ IO_AXIS_NEGATIVE_Z
ePathReferenceMode
@ PATH_REFERENCE_AUTO
@ PATH_REFERENCE_RELATIVE
@ PATH_REFERENCE_COPY
@ PATH_REFERENCE_MATCH
@ PATH_REFERENCE_ABSOLUTE
@ PATH_REFERENCE_STRIP
void OBJ_import(bContext *C, const OBJImportParams *import_params)
void OBJ_export(bContext *C, const OBJExportParams *export_params)
eOBJMtlNameCollisionMode
@ OBJ_MTL_NAME_COLLISION_MAKE_UNIQUE
@ OBJ_MTL_NAME_COLLISION_REFERENCE_EXISTING
@ PROP_HIDDEN
Definition RNA_types.hh:338
#define C
Definition RandGen.cpp:29
#define UI_ITEM_NONE
@ WM_FILESEL_FILES
Definition WM_api.hh:1125
@ WM_FILESEL_DIRECTORY
Definition WM_api.hh:1122
@ WM_FILESEL_SHOW_PROPS
Definition WM_api.hh:1127
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:1124
@ FILE_OPENFILE
Definition WM_api.hh:1133
@ FILE_SAVE
Definition WM_api.hh:1134
#define ND_OB_ACTIVE
Definition WM_types.hh:440
#define ND_OB_SELECT
Definition WM_types.hh:442
#define NC_SCENE
Definition WM_types.hh:378
@ OPTYPE_PRESET
Definition WM_types.hh:195
@ OPTYPE_UNDO
Definition WM_types.hh:182
#define ND_LAYER_CONTENT
Definition WM_types.hh:453
#define U
uint col
void WM_OT_obj_import(wmOperatorType *ot)
void WM_OT_obj_export(wmOperatorType *ot)
void file_handler_add(std::unique_ptr< FileHandlerType > file_handler)
bool poll_file_object_drop(const bContext *C, blender::bke::FileHandlerType *)
Definition io_utils.cc:58
Vector< std::string > paths_from_operator_properties(PointerRNA *ptr)
Definition io_utils.cc:75
wmOperatorStatus filesel_drop_import_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition io_utils.cc:26
void obj_file_handler_add()
const EnumPropertyItem io_transform_axis[]
void io_ui_forward_axis_update(Main *, Scene *, PointerRNA *ptr)
void io_ui_up_axis_update(Main *, Scene *, PointerRNA *ptr)
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
int RNA_int_get(PointerRNA *ptr, const char *name)
float RNA_float_get(PointerRNA *ptr, const char *name)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
void RNA_def_property_update_runtime(PropertyRNA *prop, RNAPropertyUpdateFunc func)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
char filepath[1024]
Definition BKE_main.hh:179
eEvaluationMode export_eval_mode
const char * blen_filepath
char file_base_for_tests[FILE_MAX]
ReportList * reports
char collection[MAX_ID_NAME - 2]
ePathReferenceMode path_mode
char filepath[FILE_MAX]
eOBJMtlNameCollisionMode mtl_name_collision_mode
char filepath[FILE_MAX]
struct RenderData r
void use_property_decorate_set(bool is_sep)
PanelLayout panel(const bContext *C, blender::StringRef idname, bool default_closed)
void label(blender::StringRef name, int icon)
uiLayout & column(bool align)
void use_property_split_set(bool value)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
struct ReportList * reports
struct uiLayout * layout
struct PointerRNA * ptr
void WM_event_add_fileselect(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237
void WM_operator_properties_filesel(wmOperatorType *ot, const int filter, const short type, const eFileSel_Action action, const eFileSel_Flag flag, const short display, const short sort)
bool WM_operator_winactive(bContext *C)