Skip to content

Commit d30f5fa

Browse files
authored
Merge pull request #1541 from lucienfostier/toNukeGeometryConverterTooVerbose
ToNukeGeometryConverter: Add new attribute type conversion and silent…
2 parents e37ee75 + ba11e40 commit d30f5fa

2 files changed

Lines changed: 103 additions & 0 deletions

File tree

src/IECoreNuke/ToNukeGeometryConverter.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ void writeAttribute( DD::Image::GeometryList &geoList, int objIndex, const char
6363
attr->flt() = static_cast<const IECore::FloatData *>( value )->readable();
6464
break;
6565
}
66+
case IECore::DoubleDataTypeId :
67+
{
68+
// Nuke only supports float attributes, so we narrow double to float.
69+
auto attr = geoList.writable_attribute( objIndex, GroupType::Group_Object, name, AttribType::FLOAT_ATTRIB );
70+
attr->flt() = static_cast<float>( static_cast<const IECore::DoubleData *>( value )->readable() );
71+
break;
72+
}
6673
case IECore::IntDataTypeId :
6774
{
6875
auto attr = geoList.writable_attribute( objIndex, GroupType::Group_Object, name, AttribType::INT_ATTRIB );
@@ -94,6 +101,13 @@ void writeAttribute( DD::Image::GeometryList &geoList, int objIndex, const char
94101
attr->vector3() = IECore::convert<DD::Image::Vector3>( static_cast<const IECore::V3fData *>( value )->readable() );
95102
break;
96103
}
104+
case IECore::Color3fDataTypeId :
105+
{
106+
auto attr = geoList.writable_attribute( objIndex, GroupType::Group_Object, name, AttribType::VECTOR3_ATTRIB );
107+
const auto &c = static_cast<const IECore::Color3fData *>( value )->readable();
108+
attr->vector3() = DD::Image::Vector3( c[0], c[1], c[2] );
109+
break;
110+
}
97111
case IECore::Color4fDataTypeId :
98112
{
99113
auto attr = geoList.writable_attribute( objIndex, GroupType::Group_Object, name, AttribType::VECTOR4_ATTRIB );
@@ -143,6 +157,13 @@ void writeAttribute( DD::Image::GeometryList &geoList, int objIndex, const char
143157
attr->matrix3() = result;
144158
break;
145159
}
160+
// Nuke has no equivalent for InternedString types, so we silently skip them.
161+
// We could convert InternedStringVectorData to a delimited string, but
162+
// round-tripping wouldn't be transparent — LiveScene would need special
163+
// handling to split the string back into a vector.
164+
case IECore::InternedStringDataTypeId :
165+
case IECore::InternedStringVectorDataTypeId :
166+
break;
146167
default :
147168
IECore::msg( IECore::Msg::Warning, "ToNukeGeometryConverter", boost::format( "Unsupported attribute type \"%s\" for \"%s\"" ) % value->typeName() % name );
148169
break;

test/IECoreNuke/LiveSceneKnobTest.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
514596
if __name__ == "__main__":
515597
unittest.main()
516598

0 commit comments

Comments
 (0)