@@ -511,6 +511,88 @@ def testAttributes( self ) :
511511 self .assertEqual ( attr .value , imath .M44f ( expectedAttr .value ) )
512512
513513
514+ def testAttributeTypeRoundTrip ( self ) :
515+ import imath
516+ import IECoreScene
517+ import tempfile
518+ import os
519+
520+ # Create a temporary SCC with various attribute types on a leaf location.
521+ tmpDir = tempfile .mkdtemp ()
522+ sceneFile = os .path .join ( tmpDir , "attrTypes.scc" )
523+
524+ scene = IECoreScene .SceneCache ( sceneFile , IECore .IndexedIO .OpenMode .Write )
525+ child = scene .createChild ( "obj" )
526+ child .writeObject ( IECoreScene .MeshPrimitive .createBox ( imath .Box3f ( imath .V3f ( - 1 ), imath .V3f ( 1 ) ) ), 0.0 )
527+ child .writeTransform ( IECore .M44dData ( imath .M44d () ), 0.0 )
528+
529+ child .writeAttribute ( "user:testFloat" , IECore .FloatData ( 1.5 ), 0.0 )
530+ child .writeAttribute ( "user:testDouble" , IECore .DoubleData ( 2.5 ), 0.0 )
531+ child .writeAttribute ( "user:testInt" , IECore .IntData ( 42 ), 0.0 )
532+ child .writeAttribute ( "user:testBool" , IECore .BoolData ( True ), 0.0 )
533+ child .writeAttribute ( "user:testString" , IECore .StringData ( "hello" ), 0.0 )
534+ child .writeAttribute ( "user:testInternedString" , IECore .InternedStringData ( "skipped" ), 0.0 )
535+ child .writeAttribute ( "user:testV2f" , IECore .V2fData ( imath .V2f ( 1 , 2 ) ), 0.0 )
536+ child .writeAttribute ( "user:testV3f" , IECore .V3fData ( imath .V3f ( 1 , 2 , 3 ) ), 0.0 )
537+ child .writeAttribute ( "user:testColor3f" , IECore .Color3fData ( imath .Color3f ( 0.1 , 0.2 , 0.3 ) ), 0.0 )
538+ child .writeAttribute ( "user:testColor4f" , IECore .Color4fData ( imath .Color4f ( 0.1 , 0.2 , 0.3 , 0.4 ) ), 0.0 )
539+ child .writeAttribute ( "user:testM33f" , IECore .M33fData ( imath .M33f () ), 0.0 )
540+ child .writeAttribute ( "user:testM44f" , IECore .M44fData ( imath .M44f () ), 0.0 )
541+ child .writeAttribute ( "user:testM44d" , IECore .M44dData ( imath .M44d () ), 0.0 )
542+
543+ del child , scene
544+
545+ mh = IECore .CapturingMessageHandler ()
546+ with mh :
547+ sceneReader = nuke .createNode ( "ieSceneCacheReader" )
548+ sceneReader .knob ( "file" ).setValue ( sceneFile )
549+ sceneReader .forceValidate ()
550+ widget = sceneReader .knob ( "sceneView" )
551+ widget .setSelectedItems ( ["/root/obj" ] )
552+
553+ n = nuke .createNode ( "ieLiveScene" )
554+ n .setInput ( 0 , sceneReader )
555+
556+ liveScene = n .knob ( "scene" ).getValue ()
557+ leaf = liveScene .scene ( ["obj" ] )
558+
559+ # Each attribute type round-trips through Nuke. Some types change
560+ # (e.g. DoubleData -> FloatData, Color3fData -> V3fData) because
561+ # Nuke only has float-precision attribute types.
562+ cases = [
563+ ( "user:testFloat" , IECore .FloatData , 1.5 ),
564+ ( "user:testDouble" , IECore .FloatData , 2.5 ),
565+ ( "user:testInt" , IECore .IntData , 42 ),
566+ ( "user:testBool" , IECore .IntData , 1 ),
567+ ( "user:testString" , IECore .StringData , "hello" ),
568+ ( "user:testV2f" , IECore .V2fData , imath .V2f ( 1 , 2 ) ),
569+ ( "user:testV3f" , IECore .V3fData , imath .V3f ( 1 , 2 , 3 ) ),
570+ ( "user:testColor3f" , IECore .V3fData , imath .V3f ( 0.1 , 0.2 , 0.3 ) ),
571+ ( "user:testColor4f" , IECore .Color4fData , imath .Color4f ( 0.1 , 0.2 , 0.3 , 0.4 ) ),
572+ ( "user:testM33f" , IECore .M33fData , imath .M33f () ),
573+ ( "user:testM44f" , IECore .M44fData , imath .M44f () ),
574+ ( "user:testM44d" , IECore .M44fData , imath .M44f () ),
575+ ]
576+
577+ for name , expectedType , expectedValue in cases :
578+ self .assertIn ( name , leaf .attributeNames () )
579+ self .assertTrue ( leaf .hasAttribute ( name ) )
580+ attr = leaf .readAttribute ( name , 0 )
581+ self .assertIsInstance ( attr , expectedType , f"Wrong type for { name } : { type ( attr )} " )
582+ self .assertEqual ( attr .value , expectedValue , f"Wrong value for { name } " )
583+
584+ # InternedStringData has no Nuke equivalent and should be silently skipped.
585+ self .assertNotIn ( "user:testInternedString" , leaf .attributeNames () )
586+ self .assertFalse ( leaf .hasAttribute ( "user:testInternedString" ) )
587+
588+ # No warnings should have been emitted for the skipped type.
589+ warnings = [m for m in mh .messages if m .level == IECore .Msg .Level .Warning ]
590+ self .assertEqual ( warnings , [] )
591+
592+ os .remove ( sceneFile )
593+ os .rmdir ( tmpDir )
594+
595+
514596if __name__ == "__main__" :
515597 unittest .main ()
516598
0 commit comments