8#include <pxr/usd/ar/asset.h>
9#include <pxr/usd/ar/packageUtils.h>
10#include <pxr/usd/ar/resolver.h>
11#include <pxr/usd/ar/writableAsset.h>
12#include <pxr/usd/usd/common.h>
13#include <pxr/usd/usd/stage.h>
50 for (
const std::string_view pattern :
patterns) {
51 const std::string::size_type
pos = path.find(pattern);
52 if (
pos != std::string::npos) {
53 return {path.substr(0,
pos), path.substr(
pos + pattern.size())};
66 if (pxr::ArIsPackageRelativePath(src_path)) {
67 std::pair<std::string, std::string>
split = pxr::ArSplitPackageRelativePathInner(src_path);
68 if (
split.second.empty()) {
71 "%s: Couldn't determine package-relative file name from path %s",
87 const char *dest_dir_path,
94 BLI_path_join(dest_file_path,
sizeof(dest_file_path), dest_dir_path, base_name.c_str());
98 return dest_file_path;
101 if (!
copy_asset(src_path, dest_file_path, name_collision_mode, reports)) {
104 "%s: Couldn't copy file %s to %s",
111 return dest_file_path;
115 const char *dest_dir_path,
121 if (splitPath.first.empty() || splitPath.second.empty()) {
123 reports,
RPT_ERROR,
"%s: Couldn't split UDIM pattern %s", __func__, src_path.c_str());
135 const std::string src_udim = splitPath.first + std::to_string(
i) + splitPath.second;
143 BLI_path_join(ret_udim_path,
sizeof(ret_udim_path), dest_dir_path, src_file_name.c_str());
149 if (splitPath.first.empty() || splitPath.second.empty()) {
151 return ret_udim_path;
154 return splitPath.first +
UDIM_PATTERN + splitPath.second;
158 const std::string &dst,
162 const pxr::ArResolver &ar = pxr::ArGetResolver();
165 if (!ar.Resolve(dst).IsEmpty()) {
168 reports,
RPT_INFO,
"%s: Will not overwrite existing asset %s", __func__, dst.c_str());
173 pxr::ArResolvedPath src_path = ar.Resolve(src);
175 if (src_path.IsEmpty()) {
180 pxr::ArResolvedPath dst_path = ar.ResolveForNewAsset(dst);
182 if (dst_path.IsEmpty()) {
184 reports,
RPT_ERROR,
"%s: Cannot resolve path %s for writing", __func__, dst.c_str());
188 if (src_path == dst_path) {
191 "%s: Cannot copy %s. The source and destination paths are the same",
193 src_path.GetPathString().c_str());
198 if (!ar.CanWriteAssetToPath(dst_path, &why_not)) {
201 "%s: Cannot write to asset %s: %s",
203 dst_path.GetPathString().c_str(),
208 std::shared_ptr<pxr::ArAsset> src_asset = ar.OpenAsset(src_path);
212 "%s: Cannot open source asset %s",
214 src_path.GetPathString().c_str());
218 const size_t size = src_asset->GetSize();
223 "%s: Will not copy zero size source asset %s",
225 src_path.GetPathString().c_str());
229 std::shared_ptr<const char> buf = src_asset->GetBuffer();
234 "%s: Null buffer for source asset %s",
236 src_path.GetPathString().c_str());
240 std::shared_ptr<pxr::ArWritableAsset> dst_asset = ar.OpenAssetForWrite(
241 dst_path, pxr::ArResolver::WriteMode::Replace);
245 "%s: Cannot open destination asset %s for writing",
247 src_path.GetPathString().c_str());
251 size_t bytes_written = dst_asset->Write(src_asset->GetBuffer().get(), src_asset->GetSize(), 0);
253 if (bytes_written == 0) {
256 "%s: Error writing to destination asset %s",
258 dst_path.GetPathString().c_str());
261 if (!dst_asset->Close()) {
264 "%s: Couldn't close destination asset %s",
266 dst_path.GetPathString().c_str());
270 return bytes_written > 0;
275 return !pxr::ArGetResolver().Resolve(path).IsEmpty();
279 const char *import_dir,
283 if (import_dir[0] ==
'\0') {
286 "%s: Texture import directory path empty, couldn't import %s",
293 STRNCPY(dest_dir_path, import_dir);
297 if (basepath[0] ==
'\0') {
300 "%s: import directory is relative "
301 "but the blend file path is empty. "
302 "Please save the blend file before importing the USD "
303 "or provide an absolute import directory path. "
310 STRNCPY(path_temp, dest_dir_path);
312 STRNCPY(dest_dir_path, path_temp);
320 "%s: Couldn't create texture import directory %s",
355 pxr::SdfLayerHandle layer = stage->GetRootLayer();
357 if (layer->IsAnonymous()) {
359 "%s: Cannot generate a textures directory path for anonymous stage",
364 const pxr::ArResolvedPath &stage_path = layer->GetResolvedPath();
366 if (stage_path.empty()) {
371 const pxr::ArResolver &ar = pxr::ArGetResolver();
374 std::string textures_dir = ar.CreateIdentifierForNewAsset(
"./textures", stage_path);
395 if (pxr::ArIsPackageRelativePath(path)) {
406bool paths_equal(
const std::string &path1,
const std::string &path2)
409 "Paths arguments must be absolute");
411 const pxr::ArResolver &ar = pxr::ArGetResolver();
412 return ar.ResolveForNewAsset(path1) == ar.ResolveForNewAsset(path2);
417 static bool inited =
false;
436 const pxr::ArResolver &ar = pxr::ArGetResolver();
437 pxr::ArResolvedPath resolved_path = ar.ResolveForNewAsset(path);
439 if (resolved_path.IsEmpty()) {
445 if (!ar.CanWriteAssetToPath(resolved_path, &why_not)) {
448 "Cannot write to asset %s: %s",
449 resolved_path.GetPathString().c_str(),
454 std::shared_ptr<pxr::ArWritableAsset> dst_asset = ar.OpenAssetForWrite(
455 resolved_path, pxr::ArResolver::WriteMode::Replace);
459 "Cannot open destination asset %s for writing",
460 resolved_path.GetPathString().c_str());
464 size_t bytes_written = dst_asset->Write(
data,
size, 0);
466 if (bytes_written == 0) {
469 "Error writing to destination asset %s",
470 resolved_path.GetPathString().c_str());
473 if (!dst_asset->Close()) {
476 "Couldn't close destination asset %s",
477 resolved_path.GetPathString().c_str());
481 return bytes_written > 0;
486 if (!
id || path.empty()) {
490 if (pxr::ArIsPackageRelativePath(path)) {
502 const StringRef prop_name =
"usd_source_path";
530 const StringRef prop_name =
"usd_source_path";
536 return static_cast<const char *
>(prop->
data.
pointer);
541 if (path.empty() || anchor.empty()) {
545 if (path == anchor) {
553 if (pxr::ArIsPackageRelativePath(path)) {
560 STRNCPY(rel_path, path.c_str());
578 const pxr::ArResolver &ar = pxr::ArGetResolver();
580 std::string resolved_path = ar.Resolve(path);
581 std::string resolved_anchor = ar.Resolve(anchor);
583 if (resolved_path.empty() || resolved_anchor.empty()) {
587 std::string prefix = pxr::TfStringGetCommonPrefix(path, anchor);
588 if (prefix.empty()) {
592 std::replace(prefix.begin(), prefix.end(),
'\\',
'/');
594 size_t last_slash_pos = prefix.find_last_of(
'/');
595 if (last_slash_pos == std::string::npos) {
605 resolved_path =
"/root" + resolved_path.substr(last_slash_pos);
606 resolved_anchor =
"/root" + resolved_anchor.substr(last_slash_pos);
611 if (anchor_parent_dir[0] ==
'\0') {
616 STRNCPY(result_path, resolved_path.c_str());
622 return std::string(result_path + 2);
631 pxr::ArResolvedPath resolved_path = for_import ? pxr::ArGetResolver().Resolve(path) :
632 pxr::ArGetResolver().ResolveForNewAsset(path);
634 const std::string &path_str = resolved_path.GetPathString();
636 if (!path_str.empty()) {
642 "In %s: resolved path %s exceeds path buffer length.",
IDProperty * IDP_GetPropertyFromGroup(const IDProperty *prop, blender::StringRef name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
IDProperty * IDP_New(char type, const IDPropertyTemplate *val, blender::StringRef name, eIDPropertyFlag flags={}) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
IDProperty * IDP_EnsureProperties(ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
const char * BKE_main_blendfile_path_from_global()
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert_msg(a, msg)
bool BLI_dir_create_recursive(const char *dirname) ATTR_NONNULL()
bool BLI_is_file(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
File and directory operations.
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
int BLI_path_normalize(char *path) ATTR_NONNULL(1)
#define BLI_path_join(...)
void void void BLI_path_split_file_part(const char *filepath, char *file, size_t file_maxncpy) ATTR_NONNULL(1
bool BLI_path_is_rel(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
bool void BLI_path_rel(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1)
char * STRNCPY(char(&dst)[N], const char *src)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
void BLI_string_replace_char(char *str, char src, char dst) ATTR_NONNULL(1)
static void split(const char *text, const char *seps, char ***str, int *count)
BMesh const char void * data
static const SubDPattern * patterns[]
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static std::string copy_asset_to_directory(const std::string &src_path, const char *dest_dir_path, eUSDTexNameCollisionMode name_collision_mode, ReportList *reports)
const char * temp_textures_dir()
bool should_import_asset(const std::string &path)
bool asset_exists(const std::string &path)
bool is_udim_path(const std::string &path)
std::string get_relative_path(const std::string &path, const std::string &anchor)
static std::string get_asset_base_name(const std::string &src_path, ReportList *reports)
bool write_to_path(const void *data, size_t size, const std::string &path, ReportList *reports)
bool paths_equal(const std::string &path1, const std::string &path2)
constexpr int UDIM_START_TILE
bool copy_asset(const std::string &src, const std::string &dst, eUSDTexNameCollisionMode name_collision_mode, ReportList *reports)
@ USD_TEX_NAME_COLLISION_USE_EXISTING
@ USD_TEX_NAME_COLLISION_OVERWRITE
constexpr char UDIM_PATTERN[]
void USD_path_abs(char *path, const char *basepath, bool for_import)
std::string get_export_textures_dir(const pxr::UsdStageRefPtr stage)
static std::pair< std::string, std::string > split_udim_pattern(const std::string &path)
constexpr int UDIM_END_TILE
std::string get_usd_source_path(ID *id)
void ensure_usd_source_path_prop(const std::string &path, ID *id)
constexpr char UDIM_PATTERN2[]
static bool parent_dir_exists_on_file_system(const std::string &path)
std::string import_asset(const std::string &src, const char *import_dir, eUSDTexNameCollisionMode name_collision_mode, ReportList *reports)
static std::string copy_udim_asset_to_directory(const std::string &src_path, const char *dest_dir_path, eUSDTexNameCollisionMode name_collision_mode, ReportList *reports)
void * BKE_tempdir_session
struct IDPropertyTemplate::@306303166102371126056157213146124155011254157272 string
void WM_global_reportf(eReportType type, const char *format,...)