diff --git a/src/asset-resolution.cc b/src/asset-resolution.cc index fe439fda..133cf3d8 100644 --- a/src/asset-resolution.cc +++ b/src/asset-resolution.cc @@ -58,9 +58,17 @@ bool AssetResolutionResolver::find(const std::string &assetPath) const { } } + + // TODO: Only find when input path is relative. + std::string rpath = io::FindFile(assetPath, {_current_working_path}); + if (rpath.size()) { + return true; + } + // TODO: Cache resolition. std::string fpath = io::FindFile(assetPath, _search_paths); return fpath.size(); + } std::string AssetResolutionResolver::resolve( @@ -88,8 +96,16 @@ std::string AssetResolutionResolver::resolve( } } + DCOUT("cwd = " << _current_working_path); DCOUT("search_paths = " << _search_paths); DCOUT("assetPath = " << assetPath); + + // TODO: Only find when input path is relative. + std::string rpath = io::FindFile(assetPath, {_current_working_path}); + if (rpath.size()) { + return rpath; + } + // TODO: Cache resolition. return io::FindFile(assetPath, _search_paths); } diff --git a/src/asset-resolution.hh b/src/asset-resolution.hh index 5aee81f6..97c9bfd2 100644 --- a/src/asset-resolution.hh +++ b/src/asset-resolution.hh @@ -189,10 +189,21 @@ class AssetResolutionResolver { _search_paths = paths; } - void add_seartch_path(const std::string &path) { + void add_search_path(const std::string &path) { _search_paths.push_back(path); } + // + // Asset is first seeked from the current working path(directory) when the Asset's path is a relative path. + // + void set_current_working_path(const std::string &cwp) { + _current_working_path = cwp; + } + + const std::string ¤t_working_path_str() const { + return _current_working_path; + } + const std::vector &search_paths() const { return _search_paths; } std::string search_paths_str() const; @@ -278,6 +289,7 @@ class AssetResolutionResolver { private: //ResolvePathHandler _resolve_path_handler{nullptr}; void *_userdata{nullptr}; + std::string _current_working_path{"./"}; std::vector _search_paths; mutable size_t _max_asset_bytes_in_mb{1024*1024}; // default 1 TB diff --git a/src/composition.cc b/src/composition.cc index 61214e29..fa738c14 100644 --- a/src/composition.cc +++ b/src/composition.cc @@ -130,6 +130,7 @@ bool IsBuiltinFileFormat(const std::string &name) { // TODO: support loading non-USD asset bool LoadAsset(AssetResolutionResolver &resolver, + const std::vector &search_paths, const std::map &fileformats, const value::AssetPath &assetPath, const Path &primPath, Layer *dst_layer, const PrimSpec **dst_primspec_root, @@ -169,11 +170,16 @@ bool LoadAsset(AssetResolutionResolver &resolver, } } + resolver.set_search_paths(search_paths); + + // Use resolved asset_path's basedir for current working path. // Add resolved asset_path's basedir to search path. std::string base_dir = io::GetBaseDir(resolved_path); if (base_dir.size()) { - DCOUT(fmt::format("Add {} to asset search path.", base_dir)); - resolver.add_seartch_path(base_dir); + DCOUT(fmt::format("Set `{}' to current working path.", base_dir)); + DCOUT(fmt::format("Add `{}' to asset search path.", base_dir)); + resolver.set_current_working_path(base_dir); + resolver.add_search_path(base_dir); } Asset asset; @@ -295,18 +301,20 @@ bool LoadAsset(AssetResolutionResolver &resolver, std::string default_prim; if (primPath.is_valid()) { default_prim = primPath.prim_part(); + DCOUT("primPath = " << default_prim); } else { // Use `defaultPrim` metadatum if (layer.metas().defaultPrim.valid()) { default_prim = "/" + layer.metas().defaultPrim.str(); + DCOUT("layer.meta.defaultPrim = " << default_prim); } else { // Use the first Prim in the layer. default_prim = "/" + layer.primspecs().begin()->first; + DCOUT("layer.primspecs[0].name = " << default_prim); } } if (!layer.find_primspec_at(Path(default_prim, ""), &src_ps, err)) { - DCOUT("layer = " << to_string(layer)); PUSH_ERROR_AND_RETURN( fmt::format("Failed to find PrimSpec `{}` in layer `{}`(resolved path: `{}`)", default_prim, asset_path, resolved_path)); @@ -319,6 +327,13 @@ bool LoadAsset(AssetResolutionResolver &resolver, (*dst_primspec_root) = src_ps; } + // save assetresolution state for nested composition. + layer.set_asset_resolution_state( + resolver.current_working_path_str(), + resolver.search_paths(), + resolver.get_userdata() + ); + (*dst_layer) = std::move(layer); return true; @@ -362,7 +377,7 @@ bool CompositeSublayersRec(AssetResolutionResolver &resolver, } tinyusdz::Layer sublayer; - if (!LoadAsset(resolver, options.fileformats, layer.assetPath, /* not_used */Path::make_root_path(), &sublayer, /* primspec_root */nullptr, options.error_when_no_prims_in_sublayer, options.error_when_asset_not_found, options.error_when_unsupported_fileformat, warn, err)) { + if (!LoadAsset(resolver, in_layer.get_asset_search_paths(), options.fileformats, layer.assetPath, /* not_used */Path::make_root_path(), &sublayer, /* primspec_root */nullptr, options.error_when_no_prims_in_sublayer, options.error_when_asset_not_found, options.error_when_unsupported_fileformat, warn, err)) { PUSH_ERROR_AND_RETURN(fmt::format("Load asset in subLayer failed: `{}`", layer.assetPath)); } @@ -483,6 +498,7 @@ bool CompositeSublayers(AssetResolutionResolver &resolver, namespace { bool CompositeReferencesRec(uint32_t depth, AssetResolutionResolver &resolver, + const std::vector &asset_search_paths, PrimSpec &primspec /* [inout] */, std::string *warn, std::string *err, const ReferencesCompositionOptions &options) { @@ -492,7 +508,7 @@ bool CompositeReferencesRec(uint32_t depth, AssetResolutionResolver &resolver, // Traverse children first. for (auto &child : primspec.children()) { - if (!CompositeReferencesRec(depth + 1, resolver, child, warn, err, + if (!CompositeReferencesRec(depth + 1, resolver, asset_search_paths, child, warn, err, options)) { return false; } @@ -508,7 +524,8 @@ bool CompositeReferencesRec(uint32_t depth, AssetResolutionResolver &resolver, Layer layer; const PrimSpec *src_ps{nullptr}; - if (!LoadAsset(resolver, options.fileformats, reference.asset_path, reference.prim_path, + DCOUT("reference.prim_path = " << reference.prim_path); + if (!LoadAsset(resolver, asset_search_paths, options.fileformats, reference.asset_path, reference.prim_path, &layer, &src_ps, /* error_when_no_prims_found */true, options.error_when_asset_not_found, options.error_when_unsupported_fileformat, warn, err)) { PUSH_ERROR_AND_RETURN( @@ -552,7 +569,7 @@ bool CompositeReferencesRec(uint32_t depth, AssetResolutionResolver &resolver, Layer layer; const PrimSpec *src_ps{nullptr}; - if (!LoadAsset(resolver, options.fileformats, reference.asset_path, reference.prim_path, + if (!LoadAsset(resolver, asset_search_paths, options.fileformats, reference.asset_path, reference.prim_path, &layer, &src_ps, /* error_when_no_prims */true, options.error_when_asset_not_found, options.error_when_unsupported_fileformat, warn, err)) { PUSH_ERROR_AND_RETURN( @@ -590,6 +607,7 @@ bool CompositeReferencesRec(uint32_t depth, AssetResolutionResolver &resolver, } bool CompositePayloadRec(uint32_t depth, AssetResolutionResolver &resolver, + const std::vector &asset_search_paths, PrimSpec &primspec /* [inout] */, std::string *warn, std::string *err, const PayloadCompositionOptions &options) { @@ -599,7 +617,7 @@ bool CompositePayloadRec(uint32_t depth, AssetResolutionResolver &resolver, // Traverse children first. for (auto &child : primspec.children()) { - if (!CompositePayloadRec(depth + 1, resolver, child, warn, err, options)) { + if (!CompositePayloadRec(depth + 1, resolver, asset_search_paths, child, warn, err, options)) { return false; } } @@ -620,7 +638,7 @@ bool CompositePayloadRec(uint32_t depth, AssetResolutionResolver &resolver, Layer layer; const PrimSpec *src_ps{nullptr}; - if (!LoadAsset(resolver, options.fileformats, pl.asset_path, pl.prim_path, + if (!LoadAsset(resolver, asset_search_paths, options.fileformats, pl.asset_path, pl.prim_path, &layer, &src_ps, /* error_when_no_prims_found */true, options.error_when_asset_not_found, options.error_when_unsupported_fileformat, warn, err)) { PUSH_ERROR_AND_RETURN( @@ -670,7 +688,7 @@ bool CompositePayloadRec(uint32_t depth, AssetResolutionResolver &resolver, Layer layer; const PrimSpec *src_ps{nullptr}; - if (!LoadAsset(resolver, options.fileformats, pl.asset_path, pl.prim_path, + if (!LoadAsset(resolver, asset_search_paths, options.fileformats, pl.asset_path, pl.prim_path, &layer, &src_ps, /* error_when_no_prims_found */true, options.error_when_asset_not_found, options.error_when_unsupported_fileformat, warn, err)) { PUSH_ERROR_AND_RETURN( @@ -812,10 +830,12 @@ bool CompositeReferences(AssetResolutionResolver &resolver, return false; } + std::vector search_paths = in_layer.get_asset_search_paths(); + Layer dst = in_layer; // deep copy for (auto &item : dst.primspecs()) { - if (!CompositeReferencesRec(/* depth */ 0, resolver, item.second, warn, err, + if (!CompositeReferencesRec(/* depth */ 0, resolver, search_paths, item.second, warn, err, options)) { PUSH_ERROR_AND_RETURN("Composite `references` failed."); } @@ -834,10 +854,12 @@ bool CompositePayload(AssetResolutionResolver &resolver, const Layer &in_layer, return false; } + std::vector search_paths = in_layer.get_asset_search_paths();; + Layer dst = in_layer; // deep copy for (auto &item : dst.primspecs()) { - if (!CompositePayloadRec(/* depth */ 0, resolver, item.second, warn, err, + if (!CompositePayloadRec(/* depth */ 0, resolver, search_paths, item.second, warn, err, options)) { PUSH_ERROR_AND_RETURN("Composite `payload` failed."); } @@ -1116,6 +1138,7 @@ bool InheritPrimSpec(PrimSpec &dst, const PrimSpec &src, std::string *warn, return detail::InheritPrimSpecImpl(dst, src, warn, err); } +#if 0 bool ReferenceLayerToPrimSpec(PrimSpec &dst, const Layer &layer, const Path primPath, const LayerOffset layerOffset) { @@ -1143,7 +1166,9 @@ bool ReferenceLayerToPrimSpec(PrimSpec &dst, const Layer &layer, return false; } +#endif +#if 0 bool HasReferences(const Layer &layer, const bool force_check, const ReferencesCompositionOptions options) { if (!force_check) { @@ -1171,6 +1196,7 @@ bool HasOver(const Layer &layer) { return layer.check_over_primspec(); } bool HasSpecializes(const Layer &layer) { return layer.check_unresolved_specializes(); } +#endif namespace { diff --git a/src/prim-types.hh b/src/prim-types.hh index 4cf70fbc..741065fa 100644 --- a/src/prim-types.hh +++ b/src/prim-types.hh @@ -3252,6 +3252,28 @@ class PrimSpec { return _properties; } + const std::string &get_current_working_path() const { + return _current_working_path; + } + + const std::vector &get_asset_search_paths() const { + return _asset_search_paths; + } + + void set_current_working_path(const std::string &s) { + _current_working_path = s; + } + + void set_asset_search_paths(const std::vector &search_paths) { + _asset_search_paths = search_paths; + } + + void set_asset_resolution_state( + const std::string &cwp, const std::vector &search_paths) { + _current_working_path = cwp; + _asset_search_paths = search_paths; + } + private: void CopyFrom(const PrimSpec &rhs) { _specifier = rhs._specifier; @@ -3272,6 +3294,9 @@ class PrimSpec { _variantChildren = rhs._variantChildren; _metas = rhs._metas; + + _current_working_path = rhs._current_working_path; + _asset_search_paths = rhs._asset_search_paths; } void MoveFrom(PrimSpec &rhs) { @@ -3293,6 +3318,9 @@ class PrimSpec { _variantChildren = rhs._variantChildren; _metas = std::move(rhs._metas); + + _current_working_path = rhs._current_working_path; + _asset_search_paths = rhs._asset_search_paths; } Specifier _specifier{Specifier::Def}; @@ -3321,6 +3349,15 @@ class PrimSpec { std::vector _variantChildren; PrimMeta _metas; + + /// + /// For solving asset path in nested composition. + /// Keep asset resolution state. + /// TODO: Use struct. Store userdata pointer. + /// + std::string _current_working_path{"./"}; + std::vector _asset_search_paths; + }; struct SubLayer @@ -3576,6 +3613,28 @@ struct Layer { /// bool find_primspec_at(const Path &path, const PrimSpec **ps, std::string *err) const; + + /// + /// Set state for AssetResolution in the subsequent composition operation. + /// + void set_asset_resolution_state( + const std::string &cwp, const std::vector &search_paths, void *userdata=nullptr) { + _current_working_path = cwp; + _asset_search_paths = search_paths; + _asset_resolution_userdata = userdata; + } + + void get_asset_resolution_state( + std::string &cwp, std::vector &search_paths, void *&userdata) { + cwp = _current_working_path; + search_paths = _asset_search_paths; + userdata = _asset_resolution_userdata; + } + + const std::vector get_asset_search_paths() const { + return _asset_search_paths; + } + private: std::string _name; // layer name ~= USD filename @@ -3601,6 +3660,15 @@ struct Layer { mutable bool _has_unresolved_specializes{true}; mutable bool _has_over_primspec{true}; mutable bool _has_class_primspec{true}; + + // + // Record AssetResolution state(search paths, current working directory) + // when this layer is opened by compostion(`references`, `payload`, `subLayers`) + // + mutable std::string _current_working_path{"./"}; + mutable std::vector _asset_search_paths; + mutable void *_asset_resolution_userdata{nullptr}; + };