Skip to content

Commit 00721c4

Browse files
ericmehljohnhaddon
authored andcommitted
IECoreUSD : Use / for resolved paths.
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.
1 parent cdc0cc1 commit 00721c4

File tree

4 files changed

+65
-5
lines changed

4 files changed

+65
-5
lines changed

Changes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Fixes
99
- Fixed loading of skinned facevarying normals.
1010
- `lightLink` and `shadowLink` collections on UsdLuxLightAPI are no longer treated as sets.
1111
- Version.h : Fixed `*Version()` functions to return the runtime version of the library, not the version that client code was compiled with. Use the `CORTEX_*_VERSION` macros for compile time checks.
12+
- 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`.
1213

1314
10.5.9.2 (relative to 10.5.9.1)
1415
========

contrib/IECoreUSD/src/IECoreUSD/DataAlgo.cpp

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ IECORE_POP_DEFAULT_VISIBILITY
4949

5050
#include "boost/unordered_map.hpp"
5151

52+
#ifdef _MSC_VER
53+
#include <filesystem>
54+
#endif
55+
5256
using namespace std;
5357
using namespace pxr;
5458
using namespace IECore;
@@ -92,6 +96,19 @@ GeometricData::Interpretation interpretation( TfToken role )
9296
return GeometricData::None;
9397
}
9498

99+
#ifdef _MSC_VER
100+
101+
static const bool g_forceAssetPathForwardSlash = []() -> bool {
102+
const char *c = getenv( "IECOREUSD_FORCE_ASSET_PATH_FORWARD_SLASH" );
103+
if( !c )
104+
{
105+
return true;
106+
}
107+
return strcmp( c, "0" );
108+
}();
109+
110+
#endif
111+
95112
} // namespace
96113

97114

@@ -142,9 +159,16 @@ IECore::DataPtr dataFromArray( const pxr::VtValue &value, GeometricData::Interpr
142159

143160
IECore::DataPtr dataFromSdfAssetPath( const SdfAssetPath &assetPath, const pxr::UsdAttribute *attribute = nullptr )
144161
{
145-
if( assetPath.GetResolvedPath().size() || !assetPath.GetAssetPath().size() || !attribute )
162+
163+
#ifdef _MSC_VER
164+
const std::string p = g_forceAssetPathForwardSlash ? std::filesystem::path( assetPath.GetResolvedPath() ).generic_string() : assetPath.GetResolvedPath();
165+
#else
166+
const std::string p = assetPath.GetResolvedPath();
167+
#endif
168+
169+
if( p.size() || !assetPath.GetAssetPath().size() || !attribute )
146170
{
147-
return new StringData( assetPath.GetResolvedPath() );
171+
return new StringData( p );
148172
}
149173

150174
// Path resolution failed, for a couple of possible reasons :
@@ -168,9 +192,16 @@ IECore::DataPtr dataFromSdfAssetPath( const SdfAssetPath &assetPath, const pxr::
168192
spec->GetLayer()->GetNumTimeSamplesForPath( spec->GetPath() )
169193
)
170194
{
195+
#ifdef _MSC_VER
196+
const std::string result = SdfComputeAssetPathRelativeToLayer( spec->GetLayer(), assetPath.GetAssetPath() );
197+
return new StringData(
198+
g_forceAssetPathForwardSlash ? std::filesystem::path( result ).generic_string() : result
199+
);
200+
#else
171201
return new StringData(
172202
SdfComputeAssetPathRelativeToLayer( spec->GetLayer(), assetPath.GetAssetPath() )
173203
);
204+
#endif
174205
}
175206
}
176207

contrib/IECoreUSD/src/IECoreUSD/VolumeAlgo.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@
3232
//
3333
//////////////////////////////////////////////////////////////////////////
3434

35+
#include "IECoreUSD/DataAlgo.h"
3536
#include "IECoreUSD/ObjectAlgo.h"
3637

3738
#include "IECoreVDB/VDBObject.h"
3839

3940
#include "IECore/MessageHandler.h"
41+
#include "IECore/SimpleTypedData.h"
4042

4143
IECORE_PUSH_DEFAULT_VISIBILITY
4244
#include "pxr/usd/usdVol/volume.h"
@@ -96,9 +98,8 @@ IECore::ObjectPtr readVolume( pxr::UsdVolVolume &volume, pxr::UsdTimeCode time,
9698
continue;
9799
}
98100

99-
SdfAssetPath fieldAssetPath;
100-
fieldAsset.GetFilePathAttr().Get( &fieldAssetPath, time );
101-
const std::string fieldFileName = fieldAssetPath.GetResolvedPath();
101+
ConstDataPtr fieldFileNameData = DataAlgo::fromUSD( fieldAsset.GetFilePathAttr(), time );
102+
const std::string fieldFileName = static_cast<const StringData *>( fieldFileNameData.get() )->readable();
102103

103104
if( fileName.empty() )
104105
{

contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#
3333
##########################################################################
3434

35+
import IECore
36+
3537
import importlib
3638
import os
3739
import math
@@ -4371,5 +4373,30 @@ def testWriteToOpenScene( self ) :
43714373
with self.assertRaisesRegex( RuntimeError, f"USDScene : Failed to open USD stage : '{fileName}'" ) :
43724374
IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Write )
43734375

4376+
def testAssetPathSlashes ( self ) :
4377+
4378+
root = IECoreScene.SceneInterface.create(
4379+
os.path.join( os.path.dirname( __file__ ), "data", "assetPathAttribute.usda" ),
4380+
IECore.IndexedIO.OpenMode.Read
4381+
)
4382+
xform = root.child( "xform" )
4383+
4384+
self.assertEqual( xform.attributeNames(), [ "render:testAsset" ] )
4385+
self.assertNotIn( "\\", xform.readAttribute( "render:testAsset", 0 ).value )
4386+
self.assertTrue( pathlib.Path( xform.readAttribute( "render:testAsset", 0 ).value ).is_file() )
4387+
4388+
@unittest.skipIf( not haveVDB, "No IECoreVDB" )
4389+
def testUsdVolVolumeSlashes( self ) :
4390+
4391+
import IECoreVDB
4392+
4393+
fileName = os.path.dirname( __file__ ) + "/data/volume.usda"
4394+
root = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Read )
4395+
child = root.child( "volume" )
4396+
4397+
vdbObject = child.readObject( 0 )
4398+
self.assertNotIn( "\\", vdbObject.fileName() )
4399+
self.assertTrue( pathlib.Path( vdbObject.fileName() ).is_file() )
4400+
43744401
if __name__ == "__main__":
43754402
unittest.main()

0 commit comments

Comments
 (0)