Blender V5.0
io_usd.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2019 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#ifdef WITH_USD
10# include "DNA_modifier_types.h"
11# include "DNA_space_types.h"
12
13# include "BKE_context.hh"
14# include "BKE_file_handler.hh"
15# include "BKE_report.hh"
16
17# include "BLI_path_utils.hh"
18# include "BLI_string_utf8.h"
19
20# include "BLT_translation.hh"
21
22# include "ED_fileselect.hh"
23# include "ED_object.hh"
24
25# include "MEM_guardedalloc.h"
26
27# include "RNA_access.hh"
28# include "RNA_define.hh"
29# include "RNA_enum_types.hh"
30
31# include "UI_interface.hh"
32# include "UI_interface_layout.hh"
33# include "UI_resources.hh"
34
35# include "WM_api.hh"
36# include "WM_types.hh"
37
38# include "DEG_depsgraph.hh"
39
40# include "IO_orientation.hh"
41# include "io_usd.hh"
42# include "io_utils.hh"
43# include "usd.hh"
44
45# include <pxr/pxr.h>
46
47# include <string>
48# include <utility>
49
50using namespace blender::io::usd;
51
52const EnumPropertyItem rna_enum_usd_export_evaluation_mode_items[] = {
54 "RENDER",
55 0,
56 "Render",
57 "Use Render settings for object visibility, modifier settings, etc"},
59 "VIEWPORT",
60 0,
61 "Viewport",
62 "Use Viewport settings for object visibility, modifier settings, etc"},
63 {0, nullptr, 0, nullptr, nullptr},
64};
65
66const EnumPropertyItem rna_enum_usd_mtl_name_collision_mode_items[] = {
68 "MAKE_UNIQUE",
69 0,
70 "Make Unique",
71 "Import each USD material as a unique Blender material"},
73 "REFERENCE_EXISTING",
74 0,
75 "Reference Existing",
76 "If a material with the same name already exists, reference that instead of importing"},
77 {0, nullptr, 0, nullptr, nullptr},
78};
79
80const EnumPropertyItem rna_enum_usd_property_import_mode_items[] = {
81 {USD_ATTR_IMPORT_NONE, "NONE", 0, "None", "Do not import USD custom attributes"},
83 "USER",
84 0,
85 "User",
86 "Import USD attributes in the 'userProperties' namespace as Blender custom "
87 "properties. The namespace will be stripped from the property names"},
89 "ALL",
90 0,
91 "All Custom",
92 "Import all USD custom attributes as Blender custom properties. "
93 "Namespaces will be retained in the property names"},
94 {0, nullptr, 0, nullptr, nullptr},
95};
96
97const EnumPropertyItem rna_enum_usd_tex_import_mode_items[] = {
98 {USD_TEX_IMPORT_NONE, "IMPORT_NONE", 0, "None", "Don't import textures"},
99 {USD_TEX_IMPORT_PACK, "IMPORT_PACK", 0, "Packed", "Import textures as packed data"},
100 {USD_TEX_IMPORT_COPY, "IMPORT_COPY", 0, "Copy", "Copy files to textures directory"},
101 {0, nullptr, 0, nullptr, nullptr},
102};
103
104const EnumPropertyItem rna_enum_usd_tex_name_collision_mode_items[] = {
106 "USE_EXISTING",
107 0,
108 "Use Existing",
109 "If a file with the same name already exists, use that instead of copying"},
110 {USD_TEX_NAME_COLLISION_OVERWRITE, "OVERWRITE", 0, "Overwrite", "Overwrite existing files"},
111 {0, nullptr, 0, nullptr, nullptr},
112};
113
114const EnumPropertyItem rna_enum_usd_export_subdiv_mode_items[] = {
116 "IGNORE",
117 0,
118 "Ignore",
119 "Scheme = None. Export base mesh without subdivision"},
121 "TESSELLATE",
122 0,
123 "Tessellate",
124 "Scheme = None. Export subdivided mesh"},
126 "BEST_MATCH",
127 0,
128 "Best Match",
129 "Scheme = Catmull-Clark, when possible. "
130 "Reverts to exporting the subdivided mesh for the Simple subdivision type"},
131 {0, nullptr, 0, nullptr, nullptr},
132};
133
134const EnumPropertyItem rna_enum_usd_xform_op_mode_items[] = {
136 "TRS",
137 0,
138 "Translate, Rotate, Scale",
139 "Export with translate, rotate, and scale Xform operators"},
141 "TOS",
142 0,
143 "Translate, Orient, Scale",
144 "Export with translate, orient quaternion, and scale Xform operators"},
145 {USD_XFORM_OP_MAT, "MAT", 0, "Matrix", "Export matrix operator"},
146 {0, nullptr, 0, nullptr, nullptr},
147};
148
149const EnumPropertyItem rna_enum_usdz_downscale_size[] = {
150 {USD_TEXTURE_SIZE_KEEP, "KEEP", 0, "Keep", "Keep all current texture sizes"},
151 {USD_TEXTURE_SIZE_256, "256", 0, "256", "Resize to a maximum of 256 pixels"},
152 {USD_TEXTURE_SIZE_512, "512", 0, "512", "Resize to a maximum of 512 pixels"},
153 {USD_TEXTURE_SIZE_1024, "1024", 0, "1024", "Resize to a maximum of 1024 pixels"},
154 {USD_TEXTURE_SIZE_2048, "2048", 0, "2048", "Resize to a maximum of 2048 pixels"},
155 {USD_TEXTURE_SIZE_4096, "4096", 0, "4096", "Resize to a maximum of 4096 pixels"},
156 {USD_TEXTURE_SIZE_CUSTOM, "CUSTOM", 0, "Custom", "Specify a custom size"},
157 {0, nullptr, 0, nullptr, nullptr},
158};
159
160const EnumPropertyItem rna_enum_usd_tex_export_mode_items[] = {
161 {USD_TEX_EXPORT_KEEP, "KEEP", 0, "Keep", "Use original location of textures"},
163 "PRESERVE",
164 0,
165 "Preserve",
166 "Preserve file paths of textures from already imported USD files.\n"
167 "Export remaining textures to a 'textures' folder next to the USD file"},
169 "NEW",
170 0,
171 "New Path",
172 "Export textures to a 'textures' folder next to the USD file"},
173 {0, nullptr, 0, nullptr, nullptr}};
174
175const EnumPropertyItem rna_enum_usd_mtl_purpose_items[] = {
177 "MTL_ALL_PURPOSE",
178 0,
179 "All Purpose",
180 "Attempt to import 'allPurpose' materials."},
182 "MTL_PREVIEW",
183 0,
184 "Preview",
185 "Attempt to import 'preview' materials. "
186 "Load 'allPurpose' materials as a fallback"},
188 "MTL_FULL",
189 0,
190 "Full",
191 "Attempt to import 'full' materials. "
192 "Load 'allPurpose' or 'preview' materials, in that order, as a fallback"},
193 {0, nullptr, 0, nullptr, nullptr},
194};
195
196const EnumPropertyItem rna_enum_usd_convert_scene_units_items[] = {
197 {USD_SCENE_UNITS_METERS, "METERS", 0, "Meters", "Scene meters per unit to 1.0"},
198 {USD_SCENE_UNITS_KILOMETERS, "KILOMETERS", 0, "Kilometers", "Scene meters per unit to 1000.0"},
200 "CENTIMETERS",
201 0,
202 "Centimeters",
203 "Scene meters per unit to 0.01"},
205 "MILLIMETERS",
206 0,
207 "Millimeters",
208 "Scene meters per unit to 0.001"},
209 {USD_SCENE_UNITS_INCHES, "INCHES", 0, "Inches", "Scene meters per unit to 0.0254"},
210 {USD_SCENE_UNITS_FEET, "FEET", 0, "Feet", "Scene meters per unit to 0.3048"},
211 {USD_SCENE_UNITS_YARDS, "YARDS", 0, "Yards", "Scene meters per unit to 0.9144"},
213 "CUSTOM",
214 0,
215 "Custom",
216 "Specify a custom scene meters per unit value"},
217 {0, nullptr, 0, nullptr, nullptr},
218};
219
220/* Stored in the wmOperator's customdata field to indicate it should run as a background job.
221 * This is set when the operator is invoked, and not set when it is only executed. */
222struct USDOperatorOptions {
223 bool as_background_job;
224};
225
226static void free_operator_customdata(wmOperator *op)
227{
228 if (op->customdata) {
229 USDOperatorOptions *options = static_cast<USDOperatorOptions *>(op->customdata);
231 op->customdata = nullptr;
232 }
233}
234
235/* Ensure that the prim_path is not set to
236 * the absolute root path '/'. */
237static void process_prim_path(std::string &prim_path)
238{
239 if (prim_path.empty()) {
240 return;
241 }
242
243 /* The absolute root "/" path indicates a no-op, so clear the string. */
244 if (prim_path == "/") {
245 prim_path.clear();
246 }
247 /* If a prim path doesn't start with a "/" it is invalid when creating the prim. */
248 else if (prim_path[0] != '/') {
249 prim_path.insert(0, 1, '/');
250 }
251}
252
253static wmOperatorStatus wm_usd_export_invoke(bContext *C,
254 wmOperator *op,
255 const wmEvent * /*event*/)
256{
257 USDOperatorOptions *options = MEM_callocN<USDOperatorOptions>("USDOperatorOptions");
258 options->as_background_job = true;
259 op->customdata = options;
260
262
264
266}
267
268static wmOperatorStatus wm_usd_export_exec(bContext *C, wmOperator *op)
269{
270 if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
271 BKE_report(op->reports, RPT_ERROR, "No filepath given");
272 free_operator_customdata(op);
273 return OPERATOR_CANCELLED;
274 }
275
276 const USDOperatorOptions *options = static_cast<USDOperatorOptions *>(op->customdata);
277 const bool as_background_job = (options != nullptr && options->as_background_job);
278 free_operator_customdata(op);
279
280 char filepath[FILE_MAX];
281 RNA_string_get(op->ptr, "filepath", filepath);
282
283 const eUSDTexExportMode textures_mode = eUSDTexExportMode(
284 RNA_enum_get(op->ptr, "export_textures_mode"));
285 bool export_textures = false;
286 bool use_original_paths = false;
287
288 switch (textures_mode) {
290 export_textures = false;
291 use_original_paths = true;
292 break;
294 export_textures = true;
295 use_original_paths = false;
296 break;
298 export_textures = false;
299 use_original_paths = false;
300 break;
301 default:
303 break;
304 }
305
307 params.export_animation = RNA_boolean_get(op->ptr, "export_animation");
308 params.selected_objects_only = RNA_boolean_get(op->ptr, "selected_objects_only");
309
310 params.export_meshes = RNA_boolean_get(op->ptr, "export_meshes");
311 params.export_lights = RNA_boolean_get(op->ptr, "export_lights");
312 params.convert_world_material = params.export_lights &&
313 RNA_boolean_get(op->ptr, "convert_world_material");
314 params.export_cameras = RNA_boolean_get(op->ptr, "export_cameras");
315 params.export_curves = RNA_boolean_get(op->ptr, "export_curves");
316 params.export_points = RNA_boolean_get(op->ptr, "export_points");
317 params.export_volumes = RNA_boolean_get(op->ptr, "export_volumes");
318 params.export_hair = RNA_boolean_get(op->ptr, "export_hair");
319 params.export_uvmaps = RNA_boolean_get(op->ptr, "export_uvmaps");
320 params.rename_uvmaps = RNA_boolean_get(op->ptr, "rename_uvmaps");
321 params.export_normals = RNA_boolean_get(op->ptr, "export_normals");
322 params.export_mesh_colors = RNA_boolean_get(op->ptr, "export_mesh_colors");
323 params.export_materials = RNA_boolean_get(op->ptr, "export_materials");
324
325 params.export_armatures = RNA_boolean_get(op->ptr, "export_armatures");
326 params.export_shapekeys = RNA_boolean_get(op->ptr, "export_shapekeys");
327 params.only_deform_bones = RNA_boolean_get(op->ptr, "only_deform_bones");
328
329 params.use_instancing = RNA_boolean_get(op->ptr, "use_instancing");
330 params.export_custom_properties = RNA_boolean_get(op->ptr, "export_custom_properties");
331 params.author_blender_name = RNA_boolean_get(op->ptr, "author_blender_name");
332 params.allow_unicode = RNA_boolean_get(op->ptr, "allow_unicode");
333
334 params.export_subdiv = eSubdivExportMode(RNA_enum_get(op->ptr, "export_subdivision"));
335 params.evaluation_mode = eEvaluationMode(RNA_enum_get(op->ptr, "evaluation_mode"));
336
337 params.generate_preview_surface = RNA_boolean_get(op->ptr, "generate_preview_surface");
338 params.generate_materialx_network = RNA_boolean_get(op->ptr, "generate_materialx_network");
339 params.overwrite_textures = RNA_boolean_get(op->ptr, "overwrite_textures");
340 params.relative_paths = RNA_boolean_get(op->ptr, "relative_paths");
341 params.export_textures = export_textures;
342 params.use_original_paths = use_original_paths;
343
344 params.triangulate_meshes = RNA_boolean_get(op->ptr, "triangulate_meshes");
345 params.quad_method = RNA_enum_get(op->ptr, "quad_method");
346 params.ngon_method = RNA_enum_get(op->ptr, "ngon_method");
347
348 params.convert_orientation = RNA_boolean_get(op->ptr, "convert_orientation");
349 params.forward_axis = eIOAxis(RNA_enum_get(op->ptr, "export_global_forward_selection"));
350 params.up_axis = eIOAxis(RNA_enum_get(op->ptr, "export_global_up_selection"));
351 params.xform_op_mode = eUSDXformOpMode(RNA_enum_get(op->ptr, "xform_op_mode"));
352
353 params.usdz_downscale_size = eUSDZTextureDownscaleSize(
354 RNA_enum_get(op->ptr, "usdz_downscale_size"));
355 params.usdz_downscale_custom_size = RNA_int_get(op->ptr, "usdz_downscale_custom_size");
356 params.convert_scene_units = eUSDSceneUnits(RNA_enum_get(op->ptr, "convert_scene_units"));
357 params.custom_meters_per_unit = RNA_float_get(op->ptr, "meters_per_unit");
358
359 params.merge_parent_xform = RNA_boolean_get(op->ptr, "merge_parent_xform");
360
361 params.root_prim_path = RNA_string_get(op->ptr, "root_prim_path");
362 process_prim_path(params.root_prim_path);
363
364 RNA_string_get(op->ptr, "custom_properties_namespace", params.custom_properties_namespace);
365 RNA_string_get(op->ptr, "collection", params.collection);
366
367 bool ok = USD_export(C, filepath, &params, as_background_job, op->reports);
368
369 return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
370}
371
372static void wm_usd_export_draw(bContext *C, wmOperator *op)
373{
374 uiLayout *layout = op->layout;
375 PointerRNA *ptr = op->ptr;
376
377 layout->use_property_split_set(true);
378 layout->use_property_decorate_set(false);
379
380 if (uiLayout *panel = layout->panel(C, "USD_export_general", false, IFACE_("General"))) {
381 uiLayout *col = &panel->column(false);
382 col->prop(ptr, "root_prim_path", UI_ITEM_NONE, std::nullopt, ICON_NONE);
383
384 uiLayout *sub = &col->column(true, IFACE_("Include"));
385 if (CTX_wm_space_file(C)) {
386 sub->prop(ptr, "selected_objects_only", UI_ITEM_NONE, std::nullopt, ICON_NONE);
387 }
388 sub->prop(ptr, "export_animation", UI_ITEM_NONE, std::nullopt, ICON_NONE);
389
390 sub = &col->column(true, IFACE_("Blender Data"));
391 sub->prop(ptr, "export_custom_properties", UI_ITEM_NONE, std::nullopt, ICON_NONE);
392 uiLayout *props_col = &sub->column(true);
393 props_col->prop(ptr, "custom_properties_namespace", UI_ITEM_NONE, std::nullopt, ICON_NONE);
394 props_col->prop(ptr, "author_blender_name", UI_ITEM_NONE, std::nullopt, ICON_NONE);
395 props_col->active_set(RNA_boolean_get(op->ptr, "export_custom_properties"));
396 sub->prop(ptr, "allow_unicode", UI_ITEM_NONE, std::nullopt, ICON_NONE);
397
398 sub = &col->column(true, IFACE_("File References"));
399 sub->prop(ptr, "relative_paths", UI_ITEM_NONE, std::nullopt, ICON_NONE);
400
401 col = &panel->column(false);
402 col->prop(ptr, "convert_orientation", UI_ITEM_NONE, std::nullopt, ICON_NONE);
403 if (RNA_boolean_get(ptr, "convert_orientation")) {
404 col->prop(ptr, "export_global_forward_selection", UI_ITEM_NONE, std::nullopt, ICON_NONE);
405 col->prop(ptr, "export_global_up_selection", UI_ITEM_NONE, std::nullopt, ICON_NONE);
406 }
407
408 col->prop(ptr, "convert_scene_units", UI_ITEM_NONE, std::nullopt, ICON_NONE);
409 if (eUSDSceneUnits(RNA_enum_get(ptr, "convert_scene_units")) == USD_SCENE_UNITS_CUSTOM) {
410 col->prop(ptr, "meters_per_unit", UI_ITEM_NONE, std::nullopt, ICON_NONE);
411 }
412
413 col->prop(ptr, "xform_op_mode", UI_ITEM_NONE, std::nullopt, ICON_NONE);
414
415 col = &panel->column(false);
416 col->prop(ptr, "evaluation_mode", UI_ITEM_NONE, std::nullopt, ICON_NONE);
417 }
418
419 if (uiLayout *panel = layout->panel(C, "USD_export_types", false, IFACE_("Object Types"))) {
420 uiLayout *col = &panel->column(false);
421 col->prop(ptr, "export_meshes", UI_ITEM_NONE, std::nullopt, ICON_NONE);
422 col->prop(ptr, "export_lights", UI_ITEM_NONE, std::nullopt, ICON_NONE);
423
424 uiLayout *row = &col->row(true);
425 row->prop(ptr, "convert_world_material", UI_ITEM_NONE, std::nullopt, ICON_NONE);
426 const bool export_lights = RNA_boolean_get(ptr, "export_lights");
427 row->active_set(export_lights);
428
429 col->prop(ptr, "export_cameras", UI_ITEM_NONE, std::nullopt, ICON_NONE);
430 col->prop(ptr, "export_curves", UI_ITEM_NONE, std::nullopt, ICON_NONE);
431 col->prop(ptr, "export_points", UI_ITEM_NONE, std::nullopt, ICON_NONE);
432 col->prop(ptr, "export_volumes", UI_ITEM_NONE, std::nullopt, ICON_NONE);
433 col->prop(ptr, "export_hair", UI_ITEM_NONE, std::nullopt, ICON_NONE);
434 }
435
436 if (uiLayout *panel = layout->panel(C, "USD_export_geometry", false, IFACE_("Geometry"))) {
437 uiLayout *col = &panel->column(false);
438 col->prop(ptr, "export_uvmaps", UI_ITEM_NONE, std::nullopt, ICON_NONE);
439 col->prop(ptr, "rename_uvmaps", UI_ITEM_NONE, std::nullopt, ICON_NONE);
440 col->prop(ptr, "export_normals", UI_ITEM_NONE, std::nullopt, ICON_NONE);
441
442 col->prop(ptr, "merge_parent_xform", UI_ITEM_NONE, std::nullopt, ICON_NONE);
443 col->prop(ptr, "triangulate_meshes", UI_ITEM_NONE, std::nullopt, ICON_NONE);
444 if (RNA_boolean_get(ptr, "triangulate_meshes")) {
445 col->prop(ptr, "quad_method", UI_ITEM_NONE, IFACE_("Method Quads"), ICON_NONE);
446 col->prop(ptr, "ngon_method", UI_ITEM_NONE, IFACE_("Polygons"), ICON_NONE);
447 }
448
449 col->prop(ptr, "export_subdivision", UI_ITEM_NONE, std::nullopt, ICON_NONE);
450 }
451
452 if (uiLayout *panel = layout->panel(C, "USD_export_rigging", true, IFACE_("Rigging"))) {
453 uiLayout *col = &panel->column(false);
454
455 col->prop(ptr, "export_shapekeys", UI_ITEM_NONE, std::nullopt, ICON_NONE);
456 col->prop(ptr, "export_armatures", UI_ITEM_NONE, std::nullopt, ICON_NONE);
457
458 uiLayout *row = &col->row(true);
459 row->prop(ptr, "only_deform_bones", UI_ITEM_NONE, std::nullopt, ICON_NONE);
460 row->active_set(RNA_boolean_get(ptr, "export_armatures"));
461 }
462
463 {
464 PanelLayout panel = layout->panel(C, "USD_export_materials", true);
465 panel.header->use_property_split_set(false);
466 panel.header->prop(ptr, "export_materials", UI_ITEM_NONE, "", ICON_NONE);
467 panel.header->label(IFACE_("Materials"), ICON_NONE);
468 if (panel.body) {
469 const bool export_materials = RNA_boolean_get(ptr, "export_materials");
470 panel.body->active_set(export_materials);
471
472 uiLayout *col = &panel.body->column(false);
473 col->prop(ptr, "generate_preview_surface", UI_ITEM_NONE, std::nullopt, ICON_NONE);
474 col->prop(ptr, "generate_materialx_network", UI_ITEM_NONE, std::nullopt, ICON_NONE);
475 col = &panel.body->column(true);
476 col->use_property_split_set(true);
477
478 col->prop(ptr, "export_textures_mode", UI_ITEM_NONE, std::nullopt, ICON_NONE);
479
480 const eUSDTexExportMode textures_mode = eUSDTexExportMode(
481 RNA_enum_get(op->ptr, "export_textures_mode"));
482
483 uiLayout *col2 = &col->column(true);
484 col2->use_property_split_set(true);
485 col2->enabled_set(textures_mode == USD_TEX_EXPORT_NEW_PATH);
486 col2->prop(ptr, "overwrite_textures", UI_ITEM_NONE, std::nullopt, ICON_NONE);
487 col2->prop(ptr, "usdz_downscale_size", UI_ITEM_NONE, std::nullopt, ICON_NONE);
488 if (RNA_enum_get(ptr, "usdz_downscale_size") == USD_TEXTURE_SIZE_CUSTOM) {
489 col2->prop(ptr, "usdz_downscale_custom_size", UI_ITEM_NONE, std::nullopt, ICON_NONE);
490 }
491 }
492 }
493
494 if (uiLayout *panel = layout->panel(C, "USD_export_experimental", true, IFACE_("Experimental")))
495 {
496 uiLayout *col = &panel->column(false);
497 col->prop(ptr, "use_instancing", UI_ITEM_NONE, std::nullopt, ICON_NONE);
498 }
499}
500
501static void wm_usd_export_cancel(bContext * /*C*/, wmOperator *op)
502{
503 free_operator_customdata(op);
504}
505
506static bool wm_usd_export_check(bContext * /*C*/, wmOperator *op)
507{
508 char filepath[FILE_MAX];
509 RNA_string_get(op->ptr, "filepath", filepath);
510
511 if (!BLI_path_extension_check_n(filepath, ".usd", ".usda", ".usdc", ".usdz", nullptr)) {
512 BLI_path_extension_ensure(filepath, FILE_MAX, ".usdc");
513 RNA_string_set(op->ptr, "filepath", filepath);
514 return true;
515 }
516
517 return false;
518}
519
520static void forward_axis_update(Main * /*main*/, Scene * /*scene*/, PointerRNA *ptr)
521{
522 int forward = RNA_enum_get(ptr, "export_global_forward_selection");
523 int up = RNA_enum_get(ptr, "export_global_up_selection");
524 if ((forward % 3) == (up % 3)) {
525 RNA_enum_set(ptr, "export_global_up_selection", (up + 1) % 6);
526 }
527}
528
529static void up_axis_update(Main * /*main*/, Scene * /*scene*/, PointerRNA *ptr)
530{
531 int forward = RNA_enum_get(ptr, "export_global_forward_selection");
532 int up = RNA_enum_get(ptr, "export_global_up_selection");
533 if ((forward % 3) == (up % 3)) {
534 RNA_enum_set(ptr, "export_global_forward_selection", (forward + 1) % 6);
535 }
536}
537
539{
540 ot->name = "Export USD";
541 ot->description = "Export current scene in a USD archive";
542 ot->idname = "WM_OT_usd_export";
543
544 ot->invoke = wm_usd_export_invoke;
545 ot->exec = wm_usd_export_exec;
547 ot->ui = wm_usd_export_draw;
548 ot->cancel = wm_usd_export_cancel;
549 ot->check = wm_usd_export_check;
550
551 ot->flag = OPTYPE_REGISTER | OPTYPE_PRESET; /* No UNDO possible. */
552
556 FILE_SAVE,
560
561 PropertyRNA *prop = RNA_def_string(ot->srna, "filter_glob", "*.usd", 0, "", "");
563
564 RNA_def_boolean(ot->srna,
565 "selected_objects_only",
566 false,
567 "Selection Only",
568 "Only export selected objects. Unselected parents of selected objects are "
569 "exported as empty transform");
570
571 prop = RNA_def_string(ot->srna, "collection", nullptr, MAX_ID_NAME - 2, "Collection", nullptr);
573
575 ot->srna,
576 "export_animation",
577 false,
578 "Animation",
579 "Export all frames in the render frame range, rather than only the current frame");
581 ot->srna, "export_hair", false, "Hair", "Export hair particle systems as USD curves");
583 ot->srna, "export_uvmaps", true, "UV Maps", "Include all mesh UV maps in the export");
584 RNA_def_boolean(ot->srna,
585 "rename_uvmaps",
586 true,
587 "Rename UV Maps",
588 "Rename active render UV map to \"st\" to match USD conventions");
589 RNA_def_boolean(ot->srna,
590 "export_mesh_colors",
591 true,
592 "Color Attributes",
593 "Include mesh color attributes in the export");
594 RNA_def_boolean(ot->srna,
595 "export_normals",
596 true,
597 "Normals",
598 "Include normals of exported meshes in the export");
599 RNA_def_boolean(ot->srna,
600 "export_materials",
601 true,
602 "Materials",
603 "Export viewport settings of materials as USD preview materials, and export "
604 "material assignments as geometry subsets");
605
606 RNA_def_enum(ot->srna,
607 "export_subdivision",
608 rna_enum_usd_export_subdiv_mode_items,
610 "Subdivision",
611 "Choose how subdivision modifiers will be mapped to the USD subdivision scheme "
612 "during export");
613
614 RNA_def_boolean(ot->srna,
615 "export_armatures",
616 true,
617 "Armatures",
618 "Export armatures and meshes with armature modifiers as USD skeletons and "
619 "skinned meshes");
620
621 RNA_def_boolean(ot->srna,
622 "only_deform_bones",
623 false,
624 "Only Deform Bones",
625 "Only export deform bones and their parents");
626
628 ot->srna, "export_shapekeys", true, "Shape Keys", "Export shape keys as USD blend shapes");
629
630 RNA_def_boolean(ot->srna,
631 "use_instancing",
632 false,
633 "Instancing",
634 "Export instanced objects as references in USD rather than real objects");
635
636 RNA_def_enum(ot->srna,
637 "evaluation_mode",
638 rna_enum_usd_export_evaluation_mode_items,
640 "Use Settings for",
641 "Determines visibility of objects, modifier settings, and other areas where there "
642 "are different settings for viewport and rendering");
643
644 RNA_def_boolean(ot->srna,
645 "generate_preview_surface",
646 true,
647 "USD Preview Surface Network",
648 "Generate an approximate USD Preview Surface shader "
649 "representation of a Principled BSDF node network");
650
651 RNA_def_boolean(ot->srna,
652 "generate_materialx_network",
653 false,
654 "MaterialX Network",
655 "Generate a MaterialX network representation of the materials");
656
658 ot->srna,
659 "convert_orientation",
660 false,
661 "Convert Orientation",
662 "Convert orientation axis to a different convention to match other applications");
663
664 prop = RNA_def_enum(ot->srna,
665 "export_global_forward_selection",
668 "Forward Axis",
669 "");
670 RNA_def_property_update_runtime(prop, forward_axis_update);
671
672 prop = RNA_def_enum(
673 ot->srna, "export_global_up_selection", io_transform_axis, IO_AXIS_Y, "Up Axis", "");
674 RNA_def_property_update_runtime(prop, up_axis_update);
675
676 RNA_def_enum(ot->srna,
677 "export_textures_mode",
678 rna_enum_usd_tex_export_mode_items,
680 "Export Textures",
681 "Texture export method");
682
683 RNA_def_boolean(ot->srna,
684 "overwrite_textures",
685 false,
686 "Overwrite Textures",
687 "Overwrite existing files when exporting textures");
688
689 RNA_def_boolean(ot->srna,
690 "relative_paths",
691 true,
692 "Relative Paths",
693 "Use relative paths to reference external files (i.e. textures, volumes) in "
694 "USD, otherwise use absolute paths");
695
696 RNA_def_enum(ot->srna,
697 "xform_op_mode",
698 rna_enum_usd_xform_op_mode_items,
700 "Xform Ops",
701 "The type of transform operators to write");
702
703 RNA_def_string(ot->srna,
704 "root_prim_path",
705 "/root",
706 0,
707 "Root Prim",
708 "If set, add a transform primitive with the given path to the stage "
709 "as the parent of all exported data");
710
711 RNA_def_boolean(ot->srna,
712 "export_custom_properties",
713 true,
714 "Custom Properties",
715 "Export custom properties as USD attributes");
716
717 RNA_def_string(ot->srna,
718 "custom_properties_namespace",
719 "userProperties",
721 "Namespace",
722 "If set, add the given namespace as a prefix to exported custom property names. "
723 "This only applies to property names that do not already have a prefix "
724 "(e.g., it would apply to name 'bar' but not 'foo:bar') and does not apply "
725 "to blender object and data names which are always exported in the "
726 "'userProperties:blender' namespace");
727
728 RNA_def_boolean(ot->srna,
729 "author_blender_name",
730 true,
731 "Blender Names",
732 "Author USD custom attributes containing the original Blender object and "
733 "object data names");
734
736 ot->srna,
737 "convert_world_material",
738 true,
739 "World Dome Light",
740 "Convert the world material to a USD dome light. "
741 "Currently works for simple materials, consisting of an environment texture "
742 "connected to a background shader, with an optional vector multiply of the texture color");
743
745 ot->srna,
746 "allow_unicode",
747 true,
748 "Allow Unicode",
749 "Preserve UTF-8 encoded characters when writing USD prim and property names "
750 "(requires software utilizing USD 24.03 or greater when opening the resulting files)");
751
752 RNA_def_boolean(ot->srna, "export_meshes", true, "Meshes", "Export all meshes");
753
754 RNA_def_boolean(ot->srna, "export_lights", true, "Lights", "Export all lights");
755
756 RNA_def_boolean(ot->srna, "export_cameras", true, "Cameras", "Export all cameras");
757
758 RNA_def_boolean(ot->srna, "export_curves", true, "Curves", "Export all curves");
759
760 RNA_def_boolean(ot->srna, "export_points", true, "Point Clouds", "Export all point clouds");
761
762 RNA_def_boolean(ot->srna, "export_volumes", true, "Volumes", "Export all volumes");
763
764 RNA_def_boolean(ot->srna,
765 "triangulate_meshes",
766 false,
767 "Triangulate Meshes",
768 "Triangulate meshes during export");
769
770 RNA_def_enum(ot->srna,
771 "quad_method",
774 "Quad Method",
775 "Method for splitting the quads into triangles");
776
777 RNA_def_enum(ot->srna,
778 "ngon_method",
781 "N-gon Method",
782 "Method for splitting the n-gons into triangles");
783
784 RNA_def_enum(ot->srna,
785 "usdz_downscale_size",
786 rna_enum_usdz_downscale_size,
788 "USDZ Texture Downsampling",
789 "Choose a maximum size for all exported textures");
790
791 RNA_def_int(ot->srna,
792 "usdz_downscale_custom_size",
793 128,
794 64,
795 16384,
796 "USDZ Custom Downscale Size",
797 "Custom size for downscaling exported textures",
798 128,
799 8192);
800
801 RNA_def_boolean(ot->srna,
802 "merge_parent_xform",
803 false,
804 "Merge parent Xform",
805 "Merge USD primitives with their Xform parent if possible. USD does not allow "
806 "nested UsdGeomGprims, intermediary Xform prims will be defined to keep the USD "
807 "file valid when encountering object hierarchies.");
808
809 RNA_def_enum(ot->srna,
810 "convert_scene_units",
811 rna_enum_usd_convert_scene_units_items,
813 "Units",
814 "Set the USD Stage meters per unit to the chosen measurement, or a custom value");
815
816 RNA_def_float(ot->srna,
817 "meters_per_unit",
818 1.0f,
819 0.0001f,
820 1000.0f,
821 "Meters Per Unit",
822 "Custom value for meters per unit in the USD Stage",
823 0.0001f,
824 1000.0f);
825}
826
827/* ====== USD Import ====== */
828
829static wmOperatorStatus wm_usd_import_invoke(bContext *C, wmOperator *op, const wmEvent *event)
830{
831 USDOperatorOptions *options = MEM_callocN<USDOperatorOptions>("USDOperatorOptions");
832 options->as_background_job = true;
833 op->customdata = options;
834
836}
837
838static wmOperatorStatus wm_usd_import_exec(bContext *C, wmOperator *op)
839{
840 if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
841 BKE_report(op->reports, RPT_ERROR, "No filepath given");
842 free_operator_customdata(op);
843 return OPERATOR_CANCELLED;
844 }
845
846 const USDOperatorOptions *options = static_cast<USDOperatorOptions *>(op->customdata);
847 const bool as_background_job = (options != nullptr && options->as_background_job);
848 free_operator_customdata(op);
849
850 char filepath[FILE_MAX];
851 RNA_string_get(op->ptr, "filepath", filepath);
852
853 const bool read_mesh_uvs = RNA_boolean_get(op->ptr, "read_mesh_uvs");
854 const bool read_mesh_colors = RNA_boolean_get(op->ptr, "read_mesh_colors");
855 const bool read_mesh_attributes = RNA_boolean_get(op->ptr, "read_mesh_attributes");
856
857 char mesh_read_flag = MOD_MESHSEQ_READ_VERT | MOD_MESHSEQ_READ_POLY;
858 if (read_mesh_uvs) {
859 mesh_read_flag |= MOD_MESHSEQ_READ_UV;
860 }
861 if (read_mesh_colors) {
862 mesh_read_flag |= MOD_MESHSEQ_READ_COLOR;
863 }
864 if (read_mesh_attributes) {
865 mesh_read_flag |= MOD_MESHSEQ_READ_ATTRIBUTES;
866 }
867
869 params.scale = RNA_float_get(op->ptr, "scale");
870 params.light_intensity_scale = RNA_float_get(op->ptr, "light_intensity_scale");
871 params.apply_unit_conversion_scale = RNA_boolean_get(op->ptr, "apply_unit_conversion_scale");
872
873 params.mesh_read_flag = mesh_read_flag;
874 params.set_frame_range = RNA_boolean_get(op->ptr, "set_frame_range");
875
876 /* TODO(makowalski): Add support for sequences. */
877 params.is_sequence = false;
878 params.sequence_len = 1;
879 params.offset = 0;
880 params.relative_path = RNA_boolean_get(op->ptr, "relative_path");
881
882 params.import_visible_only = RNA_boolean_get(op->ptr, "import_visible_only");
883 params.import_defined_only = RNA_boolean_get(op->ptr, "import_defined_only");
884
885 params.import_cameras = RNA_boolean_get(op->ptr, "import_cameras");
886 params.import_curves = RNA_boolean_get(op->ptr, "import_curves");
887 params.import_lights = RNA_boolean_get(op->ptr, "import_lights");
888 params.create_world_material = params.import_lights &&
889 RNA_boolean_get(op->ptr, "create_world_material");
890 params.import_materials = RNA_boolean_get(op->ptr, "import_materials");
891 params.import_all_materials = RNA_boolean_get(op->ptr, "import_all_materials");
892 params.import_meshes = RNA_boolean_get(op->ptr, "import_meshes");
893 params.import_points = RNA_boolean_get(op->ptr, "import_points");
894 params.import_subdivision = RNA_boolean_get(op->ptr, "import_subdivision");
895 params.import_volumes = RNA_boolean_get(op->ptr, "import_volumes");
896
897 params.create_collection = RNA_boolean_get(op->ptr, "create_collection");
898 params.support_scene_instancing = RNA_boolean_get(op->ptr, "support_scene_instancing");
899
900 params.import_shapes = RNA_boolean_get(op->ptr, "import_shapes");
901 params.import_skeletons = RNA_boolean_get(op->ptr, "import_skeletons");
902 params.import_blendshapes = RNA_boolean_get(op->ptr, "import_blendshapes");
903
904 params.validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes");
905 params.merge_parent_xform = RNA_boolean_get(op->ptr, "merge_parent_xform");
906
907 params.import_guide = RNA_boolean_get(op->ptr, "import_guide");
908 params.import_proxy = RNA_boolean_get(op->ptr, "import_proxy");
909 params.import_render = RNA_boolean_get(op->ptr, "import_render");
910
911 params.import_usd_preview = RNA_boolean_get(op->ptr, "import_usd_preview");
912 params.set_material_blend = RNA_boolean_get(op->ptr, "set_material_blend");
913 params.mtl_purpose = eUSDMtlPurpose(RNA_enum_get(op->ptr, "mtl_purpose"));
914 params.mtl_name_collision_mode = eUSDMtlNameCollisionMode(
915 RNA_enum_get(op->ptr, "mtl_name_collision_mode"));
916 params.import_textures_mode = eUSDTexImportMode(RNA_enum_get(op->ptr, "import_textures_mode"));
917 params.tex_name_collision_mode = eUSDTexNameCollisionMode(
918 RNA_enum_get(op->ptr, "tex_name_collision_mode"));
919
920 params.property_import_mode = eUSDPropertyImportMode(
921 RNA_enum_get(op->ptr, "property_import_mode"));
922
923 params.prim_path_mask = RNA_string_get(op->ptr, "prim_path_mask");
924
925 RNA_string_get(op->ptr, "import_textures_dir", params.import_textures_dir);
926
927 /* Switch out of edit mode to avoid being stuck in it (#54326). */
928 const Object *obedit = CTX_data_edit_object(C);
929 if (obedit) {
931 }
932
933 const bool ok = USD_import(C, filepath, &params, as_background_job, op->reports);
934
935 return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
936}
937
938static void wm_usd_import_cancel(bContext * /*C*/, wmOperator *op)
939{
940 free_operator_customdata(op);
941}
942
943static void wm_usd_import_draw(bContext *C, wmOperator *op)
944{
945 uiLayout *layout = op->layout;
946 PointerRNA *ptr = op->ptr;
947
948 layout->use_property_split_set(true);
949 layout->use_property_decorate_set(false);
950
951 if (uiLayout *panel = layout->panel(C, "USD_import_general", false, IFACE_("General"))) {
952 uiLayout *col = &panel->column(false);
953
954 col->prop(ptr, "prim_path_mask", UI_ITEM_NONE, std::nullopt, ICON_NONE);
955
956 uiLayout *sub = &col->column(true, IFACE_("Include"));
957 sub->prop(ptr, "import_visible_only", UI_ITEM_NONE, std::nullopt, ICON_NONE);
958 sub->prop(ptr, "import_defined_only", UI_ITEM_NONE, std::nullopt, ICON_NONE);
959
960 col = &panel->column(false);
961 col->prop(ptr, "set_frame_range", UI_ITEM_NONE, std::nullopt, ICON_NONE);
962 col->prop(ptr, "create_collection", UI_ITEM_NONE, std::nullopt, ICON_NONE);
963 col->prop(ptr, "relative_path", UI_ITEM_NONE, std::nullopt, ICON_NONE);
964
965 col->prop(ptr, "apply_unit_conversion_scale", UI_ITEM_NONE, std::nullopt, ICON_NONE);
966 col->prop(ptr, "scale", UI_ITEM_NONE, std::nullopt, ICON_NONE);
967 col->prop(ptr, "light_intensity_scale", UI_ITEM_NONE, std::nullopt, ICON_NONE);
968 col->prop(ptr, "property_import_mode", UI_ITEM_NONE, std::nullopt, ICON_NONE);
969 }
970
971 if (uiLayout *panel = layout->panel(C, "USD_import_types", false, IFACE_("Object Types"))) {
972 uiLayout *col = &panel->column(false);
973 col->prop(ptr, "import_cameras", UI_ITEM_NONE, std::nullopt, ICON_NONE);
974 col->prop(ptr, "import_curves", UI_ITEM_NONE, std::nullopt, ICON_NONE);
975 col->prop(ptr, "import_lights", UI_ITEM_NONE, std::nullopt, ICON_NONE);
976
977 uiLayout *row = &col->row(true);
978 row->prop(ptr, "create_world_material", UI_ITEM_NONE, std::nullopt, ICON_NONE);
979 const bool import_lights = RNA_boolean_get(ptr, "import_lights");
980 row->active_set(import_lights);
981
982 col->prop(ptr, "import_materials", UI_ITEM_NONE, std::nullopt, ICON_NONE);
983 col->prop(ptr, "import_meshes", UI_ITEM_NONE, std::nullopt, ICON_NONE);
984 col->prop(ptr, "import_volumes", UI_ITEM_NONE, std::nullopt, ICON_NONE);
985 col->prop(ptr, "import_points", UI_ITEM_NONE, std::nullopt, ICON_NONE);
986 col->prop(ptr, "import_shapes", UI_ITEM_NONE, std::nullopt, ICON_NONE);
987
988 col = &panel->column(true, IFACE_("Display Purpose"));
989 col->prop(ptr, "import_render", UI_ITEM_NONE, std::nullopt, ICON_NONE);
990 col->prop(ptr, "import_proxy", UI_ITEM_NONE, std::nullopt, ICON_NONE);
991 col->prop(ptr, "import_guide", UI_ITEM_NONE, std::nullopt, ICON_NONE);
992
993 col = &panel->column(true, IFACE_("Material Purpose"));
994 col->prop(ptr, "mtl_purpose", UI_ITEM_NONE, std::nullopt, ICON_NONE);
995 }
996
997 if (uiLayout *panel = layout->panel(C, "USD_import_geometry", true, IFACE_("Geometry"))) {
998 uiLayout *col = &panel->column(false);
999 col->prop(ptr, "read_mesh_uvs", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1000 col->prop(ptr, "read_mesh_colors", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1001 col->prop(ptr, "read_mesh_attributes", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1002 col->prop(ptr, "import_subdivision", UI_ITEM_NONE, IFACE_("Subdivision"), ICON_NONE);
1003
1004 col = &panel->column(false);
1005 col->prop(ptr, "validate_meshes", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1006 col->prop(ptr, "merge_parent_xform", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1007 }
1008
1009 if (uiLayout *panel = layout->panel(C, "USD_import_rigging", true, IFACE_("Rigging"))) {
1010 uiLayout *col = &panel->column(false);
1011 col->prop(ptr, "import_blendshapes", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1012 col->prop(ptr, "import_skeletons", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1013 }
1014
1015 if (uiLayout *panel = layout->panel(C, "USD_import_material", true, IFACE_("Materials"))) {
1016 uiLayout *col = &panel->column(false);
1017
1018 col->prop(ptr, "import_all_materials", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1019 col->prop(ptr, "import_usd_preview", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1020 col->enabled_set(RNA_boolean_get(ptr, "import_materials"));
1021
1022 uiLayout *row = &col->row(true);
1023 row->prop(ptr, "set_material_blend", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1024 row->enabled_set(RNA_boolean_get(ptr, "import_usd_preview"));
1025 col->prop(ptr, "mtl_name_collision_mode", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1026 }
1027
1028 if (uiLayout *panel = layout->panel(C, "USD_import_texture", true, IFACE_("Textures"))) {
1029 uiLayout *col = &panel->column(false);
1030
1031 col->prop(ptr, "import_textures_mode", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1032 bool copy_textures = RNA_enum_get(op->ptr, "import_textures_mode") == USD_TEX_IMPORT_COPY;
1033
1034 uiLayout *row = &col->row(true);
1035 row->prop(ptr, "import_textures_dir", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1036 row->enabled_set(copy_textures);
1037 row = &col->row(true);
1038 row->prop(ptr, "tex_name_collision_mode", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1039 row->enabled_set(copy_textures);
1040 col->enabled_set(RNA_boolean_get(ptr, "import_materials"));
1041 }
1042
1043 if (uiLayout *panel = layout->panel(
1044 C, "USD_import_instancing", true, IFACE_("Particles and Instancing")))
1045 {
1046 uiLayout *col = &panel->column(false);
1047 col->prop(ptr, "support_scene_instancing", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1048 }
1049}
1050
1052{
1053 ot->name = "Import USD";
1054 ot->description = "Import USD stage into current scene";
1055 ot->idname = "WM_OT_usd_import";
1056
1057 ot->invoke = wm_usd_import_invoke;
1058 ot->exec = wm_usd_import_exec;
1059 ot->cancel = wm_usd_import_cancel;
1060 ot->poll = WM_operator_winactive;
1061 ot->ui = wm_usd_import_draw;
1062
1063 ot->flag = OPTYPE_UNDO | OPTYPE_PRESET;
1064
1072
1073 PropertyRNA *prop = RNA_def_string(ot->srna, "filter_glob", "*.usd", 0, "", "");
1075
1077 ot->srna,
1078 "scale",
1079 1.0f,
1080 0.0001f,
1081 1000.0f,
1082 "Scale",
1083 "Value by which to enlarge or shrink the objects with respect to the world's origin",
1084 0.0001f,
1085 1000.0f);
1086
1087 RNA_def_boolean(ot->srna,
1088 "set_frame_range",
1089 true,
1090 "Set Frame Range",
1091 "Update the scene's start and end frame to match those of the USD archive");
1092
1093 RNA_def_boolean(ot->srna, "import_cameras", true, "Cameras", "");
1094 RNA_def_boolean(ot->srna, "import_curves", true, "Curves", "");
1095 RNA_def_boolean(ot->srna, "import_lights", true, "Lights", "");
1096 RNA_def_boolean(ot->srna, "import_materials", true, "Materials", "");
1097 RNA_def_boolean(ot->srna, "import_meshes", true, "Meshes", "");
1098 RNA_def_boolean(ot->srna, "import_volumes", true, "Volumes", "");
1099 RNA_def_boolean(ot->srna, "import_shapes", true, "USD Shapes", "");
1100 RNA_def_boolean(ot->srna, "import_skeletons", true, "Armatures", "");
1101 RNA_def_boolean(ot->srna, "import_blendshapes", true, "Shape Keys", "");
1102 RNA_def_boolean(ot->srna, "import_points", true, "Point Clouds", "");
1103
1104 RNA_def_boolean(ot->srna,
1105 "import_subdivision",
1106 false,
1107 "Import Subdivision Scheme",
1108 "Create subdivision surface modifiers based on the USD "
1109 "SubdivisionScheme attribute");
1110
1111 RNA_def_boolean(ot->srna,
1112 "support_scene_instancing",
1113 true,
1114 "Scene Instancing",
1115 "Import USD scene graph instances as collection instances");
1116
1117 RNA_def_boolean(ot->srna,
1118 "import_visible_only",
1119 true,
1120 "Visible Primitives Only",
1121 "Do not import invisible USD primitives. "
1122 "Only applies to primitives with a non-animated visibility attribute. "
1123 "Primitives with animated visibility will always be imported");
1124
1125 RNA_def_boolean(ot->srna,
1126 "create_collection",
1127 false,
1128 "Create Collection",
1129 "Add all imported objects to a new collection");
1130
1131 RNA_def_boolean(ot->srna, "read_mesh_uvs", true, "UV Coordinates", "Read mesh UV coordinates");
1132
1134 ot->srna, "read_mesh_colors", true, "Color Attributes", "Read mesh color attributes");
1135
1136 RNA_def_boolean(ot->srna,
1137 "read_mesh_attributes",
1138 true,
1139 "Mesh Attributes",
1140 "Read USD Primvars as mesh attributes");
1141
1142 RNA_def_string(ot->srna,
1143 "prim_path_mask",
1144 nullptr,
1145 0,
1146 "Path Mask",
1147 "Import only the primitive at the given path and its descendants. "
1148 "Multiple paths may be specified in a list delimited by commas or semicolons");
1149
1150 RNA_def_boolean(ot->srna, "import_guide", false, "Guide", "Import guide geometry");
1151
1152 RNA_def_boolean(ot->srna, "import_proxy", false, "Proxy", "Import proxy geometry");
1153
1154 RNA_def_boolean(ot->srna, "import_render", true, "Render", "Import final render geometry");
1155
1156 RNA_def_boolean(ot->srna,
1157 "import_all_materials",
1158 false,
1159 "Import All Materials",
1160 "Also import materials that are not used by any geometry. "
1161 "Note that when this option is false, materials referenced "
1162 "by geometry will still be imported");
1163
1164 RNA_def_boolean(ot->srna,
1165 "import_usd_preview",
1166 true,
1167 "Import USD Preview",
1168 "Convert UsdPreviewSurface shaders to Principled BSDF shader networks");
1169
1170 RNA_def_boolean(ot->srna,
1171 "set_material_blend",
1172 true,
1173 "Set Material Blend",
1174 "If the Import USD Preview option is enabled, "
1175 "the material blend method will automatically be set based on the "
1176 "shader's opacity and opacityThreshold inputs");
1177
1178 RNA_def_float(ot->srna,
1179 "light_intensity_scale",
1180 1.0f,
1181 0.0001f,
1182 10000.0f,
1183 "Light Intensity Scale",
1184 "Scale for the intensity of imported lights",
1185 0.0001f,
1186 1000.0f);
1187
1188 RNA_def_enum(ot->srna,
1189 "mtl_purpose",
1190 rna_enum_usd_mtl_purpose_items,
1192 "Material Purpose",
1193 "Attempt to import materials with the given purpose. "
1194 "If no material with this purpose is bound to the primitive, "
1195 "fall back on loading any other bound material");
1196
1198 ot->srna,
1199 "mtl_name_collision_mode",
1200 rna_enum_usd_mtl_name_collision_mode_items,
1202 "Material Name Collision",
1203 "Behavior when the name of an imported material conflicts with an existing material");
1204
1205 RNA_def_enum(ot->srna,
1206 "import_textures_mode",
1207 rna_enum_usd_tex_import_mode_items,
1209 "Import Textures",
1210 "Behavior when importing textures from a USDZ archive");
1211
1212 RNA_def_string(ot->srna,
1213 "import_textures_dir",
1214 "//textures/",
1216 "Textures Directory",
1217 "Path to the directory where imported textures will be copied");
1218
1220 ot->srna,
1221 "tex_name_collision_mode",
1222 rna_enum_usd_tex_name_collision_mode_items,
1224 "File Name Collision",
1225 "Behavior when the name of an imported texture file conflicts with an existing file");
1226
1227 RNA_def_enum(ot->srna,
1228 "property_import_mode",
1229 rna_enum_usd_property_import_mode_items,
1231 "Custom Properties",
1232 "Behavior when importing USD attributes as Blender custom properties");
1233
1235 ot->srna,
1236 "validate_meshes",
1237 false,
1238 "Validate Meshes",
1239 "Ensure the data is valid "
1240 "(when disabled, data may be imported which causes crashes displaying or editing)");
1241
1242 RNA_def_boolean(ot->srna,
1243 "create_world_material",
1244 true,
1245 "World Dome Light",
1246 "Convert the first discovered USD dome light to a world background shader");
1247
1248 RNA_def_boolean(ot->srna,
1249 "import_defined_only",
1250 true,
1251 "Defined Primitives Only",
1252 "Import only defined USD primitives. When disabled this allows importing USD "
1253 "primitives which are not defined, such as those with an override specifier");
1254
1255 RNA_def_boolean(ot->srna,
1256 "merge_parent_xform",
1257 true,
1258 "Merge parent Xform",
1259 "Allow USD primitives to merge with their Xform parent "
1260 "if they are the only child in the hierarchy");
1261
1263 ot->srna,
1264 "apply_unit_conversion_scale",
1265 true,
1266 "Apply Unit Conversion Scale",
1267 "Scale the scene objects by the USD stage's meters per unit value. "
1268 "This scaling is applied in addition to the value specified in the Scale option");
1269}
1270
1271namespace blender::ed::io {
1273{
1274 auto fh = std::make_unique<blender::bke::FileHandlerType>();
1275 STRNCPY_UTF8(fh->idname, "IO_FH_usd");
1276 STRNCPY_UTF8(fh->import_operator, "WM_OT_usd_import");
1277 STRNCPY_UTF8(fh->export_operator, "WM_OT_usd_export");
1278 STRNCPY_UTF8(fh->label, "Universal Scene Description");
1279 STRNCPY_UTF8(fh->file_extensions_str, ".usd;.usda;.usdc;.usdz");
1280 fh->poll_drop = poll_file_object_drop;
1281 bke::file_handler_add(std::move(fh));
1282}
1283} // namespace blender::ed::io
1284
1285#endif /* WITH_USD */
SpaceFile * CTX_wm_space_file(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
@ RPT_ERROR
Definition BKE_report.hh:39
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define FILE_MAX
bool BLI_path_extension_ensure(char *path, size_t path_maxncpy, const char *ext) ATTR_NONNULL(1
bool BLI_path_extension_check_n(const char *path,...) ATTR_NONNULL(1) ATTR_SENTINEL(0)
#define FILE_MAXDIR
#define STRNCPY_UTF8(dst, src)
#define IFACE_(msgid)
eEvaluationMode
@ DAG_EVAL_RENDER
@ DAG_EVAL_VIEWPORT
#define MAX_ID_NAME
Definition DNA_ID.h:373
#define MAX_IDPROP_NAME
Definition DNA_ID.h:186
@ MOD_TRIANGULATE_QUAD_SHORTEDGE
@ MOD_MESHSEQ_READ_COLOR
@ MOD_MESHSEQ_READ_VERT
@ MOD_MESHSEQ_READ_ATTRIBUTES
@ MOD_MESHSEQ_READ_UV
@ MOD_MESHSEQ_READ_POLY
@ MOD_TRIANGULATE_NGON_BEAUTY
@ OB_MODE_EDIT
@ FILE_SORT_DEFAULT
@ FILE_BLENDER
@ FILE_TYPE_FOLDER
@ FILE_TYPE_USD
@ FILE_DEFAULTDISPLAY
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
void ED_fileselect_ensure_default_filepath(bContext *C, wmOperator *op, const char *extension)
Definition filesel.cc:1470
eIOAxis
@ IO_AXIS_Y
@ IO_AXIS_NEGATIVE_Z
Read Guarded memory(de)allocation.
@ PROP_HIDDEN
Definition RNA_types.hh:338
#define C
Definition RandGen.cpp:29
#define UI_ITEM_NONE
@ WM_FILESEL_RELPATH
Definition WM_api.hh:1121
@ 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
@ OPTYPE_PRESET
Definition WM_types.hh:195
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
CCL_NAMESPACE_BEGIN struct Options options
uint col
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void WM_OT_usd_import(wmOperatorType *ot)
void WM_OT_usd_export(wmOperatorType *ot)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
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
wmOperatorStatus filesel_drop_import_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition io_utils.cc:26
void usd_file_handler_add()
bool mode_set(bContext *C, eObjectMode mode)
@ USD_TEX_IMPORT_NONE
Definition usd.hh:65
@ USD_TEX_IMPORT_PACK
Definition usd.hh:66
@ USD_TEX_IMPORT_COPY
Definition usd.hh:67
@ USD_XFORM_OP_TRS
Definition usd.hh:92
@ USD_XFORM_OP_TOS
Definition usd.hh:93
@ USD_XFORM_OP_MAT
Definition usd.hh:94
@ USD_SCENE_UNITS_CUSTOM
Definition usd.hh:117
@ USD_SCENE_UNITS_MILLIMETERS
Definition usd.hh:121
@ USD_SCENE_UNITS_METERS
Definition usd.hh:118
@ USD_SCENE_UNITS_CENTIMETERS
Definition usd.hh:120
@ USD_SCENE_UNITS_KILOMETERS
Definition usd.hh:119
@ USD_SCENE_UNITS_FEET
Definition usd.hh:123
@ USD_SCENE_UNITS_YARDS
Definition usd.hh:124
@ USD_SCENE_UNITS_INCHES
Definition usd.hh:122
@ USD_MTL_PURPOSE_FULL
Definition usd.hh:46
@ USD_MTL_PURPOSE_ALL
Definition usd.hh:44
@ USD_MTL_PURPOSE_PREVIEW
Definition usd.hh:45
bool USD_import(const bContext *C, const char *filepath, const USDImportParams *params, bool as_background_job, ReportList *reports)
eUSDTexNameCollisionMode
Definition usd.hh:74
@ USD_TEX_NAME_COLLISION_USE_EXISTING
Definition usd.hh:75
@ USD_TEX_NAME_COLLISION_OVERWRITE
Definition usd.hh:76
eUSDPropertyImportMode
Definition usd.hh:54
@ USD_ATTR_IMPORT_USER
Definition usd.hh:56
@ USD_ATTR_IMPORT_ALL
Definition usd.hh:57
@ USD_ATTR_IMPORT_NONE
Definition usd.hh:55
@ USD_SUBDIV_TESSELLATE
Definition usd.hh:83
@ USD_SUBDIV_BEST_MATCH
Definition usd.hh:88
@ USD_SUBDIV_IGNORE
Definition usd.hh:81
bool USD_export(const bContext *C, const char *filepath, const USDExportParams *params, bool as_background_job, ReportList *reports)
@ USD_TEX_EXPORT_KEEP
Definition usd.hh:111
@ USD_TEX_EXPORT_PRESERVE
Definition usd.hh:112
@ USD_TEX_EXPORT_NEW_PATH
Definition usd.hh:113
eUSDMtlNameCollisionMode
Definition usd.hh:35
@ USD_MTL_NAME_COLLISION_MAKE_UNIQUE
Definition usd.hh:36
@ USD_MTL_NAME_COLLISION_REFERENCE_EXISTING
Definition usd.hh:37
eUSDZTextureDownscaleSize
Definition usd.hh:97
@ USD_TEXTURE_SIZE_256
Definition usd.hh:100
@ USD_TEXTURE_SIZE_CUSTOM
Definition usd.hh:98
@ USD_TEXTURE_SIZE_2048
Definition usd.hh:103
@ USD_TEXTURE_SIZE_4096
Definition usd.hh:104
@ USD_TEXTURE_SIZE_KEEP
Definition usd.hh:99
@ USD_TEXTURE_SIZE_1024
Definition usd.hh:102
@ USD_TEXTURE_SIZE_512
Definition usd.hh:101
const EnumPropertyItem io_transform_axis[]
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)
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)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
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_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)
const EnumPropertyItem rna_enum_modifier_triangulate_ngon_method_items[]
const EnumPropertyItem rna_enum_modifier_triangulate_quad_method_items[]
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 active_set(bool active)
void enabled_set(bool enabled)
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)
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)