#99807: Add support for exporting to USDZ - ultimate fixes #105185
|
@ -57,8 +57,8 @@ int BLI_delete(const char *file, bool dir, bool recursive) ATTR_NONNULL();
|
|||
* \return zero on success (matching 'remove' behavior).
|
||||
*/
|
||||
int BLI_delete_soft(const char *file, const char **error_message) ATTR_NONNULL();
|
||||
int BLI_path_move(const char *path, const char *to) ATTR_NONNULL();
|
||||
#if 0 /* Unused */
|
||||
int BLI_move(const char *path, const char *to) ATTR_NONNULL();
|
||||
int BLI_create_symlink(const char *path, const char *to) ATTR_NONNULL();
|
||||
#endif
|
||||
|
||||
|
|
|
@ -458,9 +458,7 @@ int BLI_delete_soft(const char *file, const char **error_message)
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Not used anywhere! */
|
||||
# if 0
|
||||
int BLI_move(const char *file, const char *to)
|
||||
int BLI_path_move(const char *file, const char *to)
|
||||
{
|
||||
char str[MAXPATHLEN + 12];
|
||||
int err;
|
||||
|
@ -490,7 +488,6 @@ int BLI_move(const char *file, const char *to)
|
|||
|
||||
return err;
|
||||
}
|
||||
# endif
|
||||
|
||||
int BLI_copy(const char *file, const char *to)
|
||||
{
|
||||
|
@ -822,8 +819,8 @@ static int delete_soft(const char *file, const char **error_message)
|
|||
|
||||
Class NSStringClass = objc_getClass("NSString");
|
||||
SEL stringWithUTF8StringSel = sel_registerName("stringWithUTF8String:");
|
||||
id pathString = ((
|
||||
id(*)(Class, SEL, const char *))objc_msgSend)(NSStringClass, stringWithUTF8StringSel, file);
|
||||
id pathString = ((id(*)(Class, SEL, const char *))objc_msgSend)(
|
||||
NSStringClass, stringWithUTF8StringSel, file);
|
||||
|
||||
Class NSFileManagerClass = objc_getClass("NSFileManager");
|
||||
SEL defaultManagerSel = sel_registerName("defaultManager");
|
||||
|
@ -834,8 +831,8 @@ static int delete_soft(const char *file, const char **error_message)
|
|||
id nsurl = ((id(*)(Class, SEL, id))objc_msgSend)(NSURLClass, fileURLWithPathSel, pathString);
|
||||
|
||||
SEL trashItemAtURLSel = sel_registerName("trashItemAtURL:resultingItemURL:error:");
|
||||
BOOL deleteSuccessful = ((
|
||||
BOOL(*)(id, SEL, id, id, id))objc_msgSend)(fileManager, trashItemAtURLSel, nsurl, nil, nil);
|
||||
BOOL deleteSuccessful = ((BOOL(*)(id, SEL, id, id, id))objc_msgSend)(
|
||||
fileManager, trashItemAtURLSel, nsurl, nil, nil);
|
||||
|
||||
if (deleteSuccessful) {
|
||||
ret = 0;
|
||||
|
@ -1123,8 +1120,6 @@ static int copy_single_file(const char *from, const char *to)
|
|||
return RecursiveOp_Callback_OK;
|
||||
}
|
||||
|
||||
/* Not used anywhere! */
|
||||
# if 0
|
||||
static int move_callback_pre(const char *from, const char *to)
|
||||
{
|
||||
int ret = rename(from, to);
|
||||
|
@ -1149,7 +1144,7 @@ static int move_single_file(const char *from, const char *to)
|
|||
|
||||
/* if *file represents a directory, moves all its contents into *to, else renames
|
||||
* file itself to *to. */
|
||||
int BLI_move(const char *file, const char *to)
|
||||
int BLI_path_move(const char *file, const char *to)
|
||||
{
|
||||
int ret = recursive_operation(file, to, move_callback_pre, move_single_file, NULL);
|
||||
|
||||
|
@ -1159,7 +1154,6 @@ int BLI_move(const char *file, const char *to)
|
|||
|
||||
return ret;
|
||||
}
|
||||
# endif
|
||||
|
||||
static const char *check_destination(const char *file, const char *to)
|
||||
{
|
||||
|
|
|
@ -49,9 +49,18 @@ struct ExportJobData {
|
|||
bool export_ok;
|
||||
timeit::TimePoint start_time;
|
||||
|
||||
const bool targets_usdz() const
|
||||
{
|
||||
if (usdz_filepath) {
|
||||
return usdz_filepath[0];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *export_filepath() const
|
||||
{
|
||||
if (strlen(usdz_filepath) > 0) {
|
||||
if (targets_usdz()) {
|
||||
return usdz_filepath;
|
||||
}
|
||||
return unarchived_filepath;
|
||||
|
@ -90,8 +99,8 @@ static bool perform_usdz_conversion(const ExportJobData *data)
|
|||
pxr::UsdUtilsCreateNewUsdzPackage(pxr::SdfAssetPath(usdc_file), usdz_file);
|
||||
BLI_change_working_dir(original_working_dir);
|
||||
|
||||
char usdz_temp_dirfile[FILE_MAX];
|
||||
BLI_path_join(usdz_temp_dirfile, FILE_MAX, usdc_temp_dir, usdz_file);
|
||||
char usdz_temp_full_path[FILE_MAX];
|
||||
BLI_path_join(usdz_temp_full_path, FILE_MAX, usdc_temp_dir, usdz_file);
|
||||
|
||||
int result = 0;
|
||||
if (BLI_exists(data->usdz_filepath)) {
|
||||
|
@ -102,11 +111,11 @@ static bool perform_usdz_conversion(const ExportJobData *data)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
result = BLI_rename(usdz_temp_dirfile, data->usdz_filepath);
|
||||
result = BLI_path_move(usdz_temp_full_path, data->usdz_filepath);
|
||||
if (result != 0) {
|
||||
WM_reportf(RPT_ERROR,
|
||||
"USD Export: Couldn't move new usdz file from temporary location %s to %s",
|
||||
usdz_temp_dirfile,
|
||||
usdz_temp_full_path,
|
||||
data->usdz_filepath);
|
||||
return false;
|
||||
}
|
||||
|
@ -218,8 +227,9 @@ static void export_startjob(void *customdata,
|
|||
BKE_scene_graph_update_for_newframe(data->depsgraph);
|
||||
}
|
||||
|
||||
if (strlen(data->usdz_filepath) > 0) {
|
||||
if (!perform_usdz_conversion(data)) {
|
||||
if (data->targets_usdz()) {
|
||||
bool usd_conversion_success = perform_usdz_conversion(data);
|
||||
if (!usd_conversion_success) {
|
||||
data->export_ok = false;
|
||||
*progress = 1.0f;
|
||||
*do_update = true;
|
||||
|
@ -256,7 +266,7 @@ static void export_endjob(void *customdata)
|
|||
|
||||
DEG_graph_free(data->depsgraph);
|
||||
|
||||
if (strlen(data->usdz_filepath) > 0) {
|
||||
if (data->targets_usdz()) {
|
||||
export_endjob_usdz_cleanup(data);
|
||||
}
|
||||
|
||||
|
@ -275,7 +285,7 @@ static void export_endjob(void *customdata)
|
|||
|
||||
/* To create a usdz file, we must first create a .usd/a/c file and then covert it to .usdz. The
|
||||
* temporary files will be created in Blender's temporary session storage. The .usdz file will then
|
||||
* copied to job->usdz_filepath. */
|
||||
* be moved to job->usdz_filepath. */
|
||||
static void create_temp_path_for_usdz_export(const char *filepath,
|
||||
blender::io::usd::ExportJobData *job)
|
||||
{
|
||||
|
@ -292,7 +302,7 @@ static void create_temp_path_for_usdz_export(const char *filepath,
|
|||
MEM_freeN(usdc_file);
|
||||
}
|
||||
|
||||
static void set_job_filepath(const char *filepath, blender::io::usd::ExportJobData *job)
|
||||
static void set_job_filepath(blender::io::usd::ExportJobData *job, const char *filepath)
|
||||
{
|
||||
if (BLI_path_extension_check_n(filepath, ".usdz", NULL)) {
|
||||
create_temp_path_for_usdz_export(filepath, job);
|
||||
|
@ -317,7 +327,7 @@ bool USD_export(bContext *C,
|
|||
job->bmain = CTX_data_main(C);
|
||||
job->wm = CTX_wm_manager(C);
|
||||
job->export_ok = false;
|
||||
set_job_filepath(filepath, job);
|
||||
set_job_filepath(job, filepath);
|
||||
|
||||
job->depsgraph = DEG_graph_new(job->bmain, scene, view_layer, params->evaluation_mode);
|
||||
job->params = *params;
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace blender::io::usd {
|
|||
|
||||
const StringRefNull usdz_export_test_filename = "usd/usdz_export_test.blend";
|
||||
char temp_dir[FILE_MAX];
|
||||
char temp_output_dir[FILE_MAX];
|
||||
char output_filename[FILE_MAX];
|
||||
|
||||
class UsdUsdzExportTest : public BlendfileLoadingBaseTest {
|
||||
|
@ -57,12 +58,16 @@ class UsdUsdzExportTest : public BlendfileLoadingBaseTest {
|
|||
char original_wd[FILE_MAX];
|
||||
BLI_current_working_dir(original_wd, FILE_MAX);
|
||||
|
||||
BLI_path_join(temp_dir, FILE_MAX, original_wd, "test_temp_dir");
|
||||
BLI_dir_create_recursive(temp_dir);
|
||||
BKE_tempdir_init(temp_dir);
|
||||
BKE_tempdir_init(nullptr);
|
||||
const char *temp_base_dir = BKE_tempdir_base();
|
||||
|
||||
const std::string &test_assets_dir = blender::tests::flags_test_asset_dir();
|
||||
BLI_path_join(output_filename, FILE_MAX, test_assets_dir.c_str(), "usd/output_новый.usdz");
|
||||
BLI_path_join(temp_dir, FILE_MAX, temp_base_dir, "usdz_test_temp_dir");
|
||||
BLI_dir_create_recursive(temp_dir);
|
||||
|
||||
BLI_path_join(temp_output_dir, FILE_MAX, temp_base_dir, "usdz_test_output_dir");
|
||||
BLI_dir_create_recursive(temp_output_dir);
|
||||
|
||||
BLI_path_join(output_filename, FILE_MAX, temp_output_dir, "output_новый.usdz");
|
||||
}
|
||||
|
||||
virtual void TearDown() override
|
||||
|
@ -71,10 +76,8 @@ class UsdUsdzExportTest : public BlendfileLoadingBaseTest {
|
|||
CTX_free(context);
|
||||
context = nullptr;
|
||||
|
||||
if (BLI_exists(output_filename)) {
|
||||
BLI_delete(output_filename, false, false);
|
||||
BLI_delete(temp_dir, true, true);
|
||||
}
|
||||
BLI_delete(temp_dir, true, true);
|
||||
BLI_delete(temp_output_dir, true, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -86,31 +89,32 @@ TEST_F(UsdUsdzExportTest, usdz_export)
|
|||
}
|
||||
|
||||
/* File sanity check. */
|
||||
EXPECT_EQ(BLI_listbase_count(&bfile->main->objects), 4);
|
||||
ASSERT_EQ(BLI_listbase_count(&bfile->main->objects), 4)
|
||||
<< "Blender scene should have 4 objects.";
|
||||
|
||||
USDExportParams params{};
|
||||
|
||||
bool result = USD_export(context, output_filename, ¶ms, false);
|
||||
EXPECT_TRUE(result);
|
||||
ASSERT_TRUE(result) << "usd export to " << output_filename << " failed.";
|
||||
|
||||
pxr::UsdStageRefPtr stage = pxr::UsdStage::Open(output_filename);
|
||||
EXPECT_TRUE(bool(stage));
|
||||
ASSERT_TRUE(bool(stage)) << "unable to open stage for the exported usdz file.";
|
||||
|
||||
std::string prim_name = pxr::TfMakeValidIdentifier("Cube");
|
||||
pxr::UsdPrim test_prim = stage->GetPrimAtPath(pxr::SdfPath("/Cube/" + prim_name));
|
||||
EXPECT_TRUE(bool(test_prim));
|
||||
EXPECT_TRUE(bool(test_prim)) << "Cube prim should exist in exported usdz file.";
|
||||
|
||||
prim_name = pxr::TfMakeValidIdentifier("Cylinder");
|
||||
test_prim = stage->GetPrimAtPath(pxr::SdfPath("/Cylinder/" + prim_name));
|
||||
EXPECT_TRUE(bool(test_prim));
|
||||
EXPECT_TRUE(bool(test_prim)) << "Cylinder prim should exist in exported usdz file.";
|
||||
|
||||
prim_name = pxr::TfMakeValidIdentifier("Icosphere");
|
||||
test_prim = stage->GetPrimAtPath(pxr::SdfPath("/Icosphere/" + prim_name));
|
||||
EXPECT_TRUE(bool(test_prim));
|
||||
EXPECT_TRUE(bool(test_prim)) << "Icosphere prim should exist in exported usdz file.";
|
||||
|
||||
prim_name = pxr::TfMakeValidIdentifier("Sphere");
|
||||
test_prim = stage->GetPrimAtPath(pxr::SdfPath("/Sphere/" + prim_name));
|
||||
EXPECT_TRUE(bool(test_prim));
|
||||
EXPECT_TRUE(bool(test_prim)) << "Sphere prim should exist in exported usdz file.";
|
||||
}
|
||||
|
||||
} // namespace blender::io::usd
|
Loading…
Reference in New Issue