Skip to content

Commit

Permalink
IECoreUSD : Use / for resolved paths.
Browse files Browse the repository at this point in the history
On Windows, the result of USD's `GetResolvedPath()` method returns the
resolved path using `\` between directories. This can cause problems
when doing string substition on a resolved path since the `\` will be
interpreted as the start of an escape character. Using `/` also
conforms to Cortex's standard of always using `/` for paths because they
work on all operating systems.
  • Loading branch information
ericmehl committed Jul 25, 2024
1 parent 0f34fb8 commit a9eea20
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 3 deletions.
3 changes: 3 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
10.5.x.x (relative to 10.5.9.1)
========

Fixes
-----

- IECoreUSD : Asset and volume paths now use `/` in the resolved path on all operating systems. This behavior can be disabled by setting the `IECOREUSD_FORCE_ASSET_PATH_FORWARD_SLASH` environment variable to a value of `0`.

10.5.9.1 (relative to 10.5.9.0)
========
Expand Down
18 changes: 16 additions & 2 deletions contrib/IECoreUSD/src/IECoreUSD/DataAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ IECORE_POP_DEFAULT_VISIBILITY

#include "boost/unordered_map.hpp"

#include <filesystem>

using namespace std;
using namespace pxr;
using namespace IECore;
Expand Down Expand Up @@ -92,6 +94,15 @@ GeometricData::Interpretation interpretation( TfToken role )
return GeometricData::None;
}

static const bool g_forceAssetPathForwardSlash = []() -> bool {
const char *c = getenv( "IECOREUSD_FORCE_ASSET_PATH_FORWARD_SLASH" );
if( !c )
{
return true;
}
return strcmp( c, "0" );
}();

} // namespace


Expand Down Expand Up @@ -142,9 +153,12 @@ IECore::DataPtr dataFromArray( const pxr::VtValue &value, GeometricData::Interpr

IECore::DataPtr dataFromSdfAssetPath( const SdfAssetPath &assetPath, const pxr::UsdAttribute *attribute = nullptr )
{
if( assetPath.GetResolvedPath().size() || !assetPath.GetAssetPath().size() || !attribute )
const std::string p = assetPath.GetResolvedPath();
if( p.size() || !assetPath.GetAssetPath().size() || !attribute )
{
return new StringData( assetPath.GetResolvedPath() );
return new StringData(
g_forceAssetPathForwardSlash ? std::filesystem::path( p ).generic_string() : p
);
}

// Path resolution failed, for a couple of possible reasons :
Expand Down
14 changes: 13 additions & 1 deletion contrib/IECoreUSD/src/IECoreUSD/VolumeAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ IECORE_PUSH_DEFAULT_VISIBILITY
#include "pxr/usd/usdVol/openVDBAsset.h"
IECORE_POP_DEFAULT_VISIBILITY

#include <filesystem>

using namespace pxr;
using namespace IECore;
using namespace IECoreScene;
Expand Down Expand Up @@ -81,6 +83,15 @@ using namespace IECoreUSD;
namespace
{

static const bool g_forceAssetPathForwardSlash = []() -> bool {
const char *c = getenv( "IECOREUSD_FORCE_ASSET_PATH_FORWARD_SLASH" );
if( !c )
{
return true;
}
return strcmp( c, "0" );
}();

IECore::ObjectPtr readVolume( pxr::UsdVolVolume &volume, pxr::UsdTimeCode time, const Canceller *canceller )
{
std::string fileName;
Expand All @@ -98,7 +109,8 @@ IECore::ObjectPtr readVolume( pxr::UsdVolVolume &volume, pxr::UsdTimeCode time,

SdfAssetPath fieldAssetPath;
fieldAsset.GetFilePathAttr().Get( &fieldAssetPath, time );
const std::string fieldFileName = fieldAssetPath.GetResolvedPath();
const std::string p = fieldAssetPath.GetResolvedPath();
const std::string fieldFileName = g_forceAssetPathForwardSlash ? std::filesystem::path( p ).generic_string() : p;

if( fileName.empty() )
{
Expand Down
25 changes: 25 additions & 0 deletions contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
#
##########################################################################

import IECore

import importlib
import os
import math
Expand Down Expand Up @@ -4257,5 +4259,28 @@ def testPerPurposeModelBound( self ) :
self.assertTrue( root.child( "group" ).hasBound() )
self.assertEqual( root.child( "group" ).readBound( 0 ), imath.Box3d( imath.V3d( -1 ), imath.V3d( 1 ) ) )

def testAsetPathSlashes ( self ) :

root = IECoreScene.SceneInterface.create(
os.path.join( os.path.dirname( __file__ ), "data", "assetPathAttribute.usda" ),
IECore.IndexedIO.OpenMode.Read
)
xform = root.child( "xform" )

self.assertEqual( xform.attributeNames(), [ "render:testAsset" ] )
self.assertNotIn( "\\", xform.readAttribute( "render:testAsset", 0 ).value )

@unittest.skipIf( not haveVDB, "No IECoreVDB" )
def testUsdVolVolumeSlashes( self ) :

import IECoreVDB

fileName = os.path.dirname( __file__ ) + "/data/volume.usda"
root = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Read )
child = root.child( "volume" )

vdbObject = child.readObject( 0 )
self.assertNotIn( "\\", vdbObject.fileName() )

if __name__ == "__main__":
unittest.main()

0 comments on commit a9eea20

Please sign in to comment.