示例#1
0
    def testShapeAttributes(self):

        r = IECoreArnold.Renderer()

        r.display("test", "ieDisplay", "rgba", {
            "driverType": "ImageDisplayDriver",
            "handle": "test"
        })

        with IECore.WorldBlock(r):

            r.concatTransform(
                IECore.M44f.createTranslated(IECore.V3f(0, 0, -5)))

            r.setAttribute("ai:polymesh:subdiv_iterations", IECore.IntData(10))

            mesh = IECore.MeshPrimitive.createPlane(
                IECore.Box2f(IECore.V2f(-2), IECore.V2f(2)))
            mesh.render(r)

            shapes = self.__allNodes(type=arnold.AI_NODE_SHAPE)

            self.assertEqual(len(shapes), 1)
            self.assertEqual(
                arnold.AiNodeGetInt(shapes[0], "subdiv_iterations"), 10)
示例#2
0
	def testFrameAndAASeed( self ) :

		options = GafferArnold.ArnoldOptions()

		render = GafferArnold.ArnoldRender()
		render["in"].setInput( options["out"] )
		render["mode"].setValue( render.Mode.SceneDescriptionMode )
		render["fileName"].setValue( self.temporaryDirectory() + "/test.ass" )

		for frame in ( 1, 2, 2.8, 3.2 ) :
			for seed in ( None, 3, 4 ) :
				with Gaffer.Context() as c :

					c.setFrame( frame )

					options["options"]["aaSeed"]["enabled"].setValue( seed is not None )
					options["options"]["aaSeed"]["value"].setValue( seed or 1 )

					render["task"].execute()

					with IECoreArnold.UniverseBlock( writable = True ) :

						arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" )

						self.assertEqual(
							arnold.AiNodeGetInt( arnold.AiUniverseGetOptions(), "AA_seed" ),
							seed or round( frame )
						)
示例#3
0
    def testEnumAttributes(self):

        for source, result in [(IECore.StringData("catclark"), 1),
                               (IECore.StringData("linear"), 2),
                               (IECore.IntData(1), 1), (IECore.IntData(2), 2)]:

            r = IECoreArnold.Renderer()

            r.display("test", "ieDisplay", "rgba", {
                "driverType": "ImageDisplayDriver",
                "handle": "test"
            })

            with IECore.WorldBlock(r):

                r.concatTransform(
                    IECore.M44f.createTranslated(IECore.V3f(0, 0, -5)))

                r.setAttribute("ai:polymesh:subdiv_type", source)

                mesh = IECore.MeshPrimitive.createPlane(
                    IECore.Box2f(IECore.V2f(-2), IECore.V2f(2)))
                mesh.render(r)

                shapes = self.__allNodes(type=arnold.AI_NODE_SHAPE)

                self.assertEqual(len(shapes), 1)
                self.assertEqual(arnold.AiNodeGetInt(shapes[0], "subdiv_type"),
                                 result)

            del r
示例#4
0
    def testIntData(self):

        with IECoreArnold.UniverseBlock(writable=True):

            n = arnold.AiNode("standard_surface")
            IECoreArnold.ParameterAlgo.setParameter(n, "customInt",
                                                    IECore.IntData(42))
            IECoreArnold.ParameterAlgo.setParameter(n, "customUInt",
                                                    IECore.UIntData(43))
            IECoreArnold.ParameterAlgo.setParameter(
                n, "customIntVectorData", IECore.IntVectorData([5, 6, 7]))
            IECoreArnold.ParameterAlgo.setParameter(
                n, "customUIntVectorData",
                IECore.UIntVectorData([12, 2147483649]))

            self.assertEqual(arnold.AiNodeGetInt(n, "customInt"), 42)
            self.assertEqual(arnold.AiNodeGetUInt(n, "customUInt"), 43)
            a = arnold.AiNodeGetArray(n, "customIntVectorData")
            self.assertEqual(arnold.AiArrayGetNumElements(a.contents), 3)
            self.assertEqual(arnold.AiArrayGetInt(a, 0), 5)
            self.assertEqual(arnold.AiArrayGetInt(a, 1), 6)
            self.assertEqual(arnold.AiArrayGetInt(a, 2), 7)
            a = arnold.AiNodeGetArray(n, "customUIntVectorData")
            self.assertEqual(arnold.AiArrayGetNumElements(a.contents), 2)
            self.assertEqual(arnold.AiArrayGetUInt(a, 0), 12)
            self.assertEqual(arnold.AiArrayGetUInt(a, 1), 2147483649)
示例#5
0
	def testPrimitiveVariables( self ) :

		s = IECore.SpherePrimitive()
		s["v"] = IECore.PrimitiveVariable( IECore.PrimitiveVariable.Interpolation.Constant, IECore.V3f( 1, 2, 3 ) )
		s["c"] = IECore.PrimitiveVariable( IECore.PrimitiveVariable.Interpolation.Constant, IECore.Color3f( 1, 2, 3 ) )
		s["s"] = IECore.PrimitiveVariable( IECore.PrimitiveVariable.Interpolation.Constant, "test" )
		s["i"] = IECore.PrimitiveVariable( IECore.PrimitiveVariable.Interpolation.Constant, 11 )
		s["b"] = IECore.PrimitiveVariable( IECore.PrimitiveVariable.Interpolation.Constant, True )
		s["f"] = IECore.PrimitiveVariable( IECore.PrimitiveVariable.Interpolation.Constant, 2.5 )
		s["m"] = IECore.PrimitiveVariable( IECore.PrimitiveVariable.Interpolation.Constant, IECore.M44f( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) )

		with IECoreArnold.UniverseBlock( writable = True ) :

			n = IECoreArnold.NodeAlgo.convert( s, "testSphere" )
			self.assertEqual( arnold.AiNodeGetVec( n, "v" ), arnold.AtVector( 1, 2, 3 ) )
			self.assertEqual( arnold.AiNodeGetRGB( n, "c" ), arnold.AtRGB( 1, 2, 3 ) )
			self.assertEqual( arnold.AiNodeGetStr( n, "s" ), "test" )
			self.assertEqual( arnold.AiNodeGetInt( n, "i" ), 11 )
			self.assertEqual( arnold.AiNodeGetBool( n, "b" ), True )
			self.assertEqual( arnold.AiNodeGetFlt( n, "f" ), 2.5 )

			m = arnold.AiNodeGetMatrix( n, "m" )
			self.assertEqual(
				[ list( i ) for i in m.data ],
				[ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16] ],
			)
示例#6
0
	def testUniformPrimitiveVariable( self ) :

		p = IECore.PointsPrimitive( IECore.V3fVectorData( 10 ) )
		p["myPrimVar"] = IECore.PrimitiveVariable( IECore.PrimitiveVariable.Interpolation.Uniform, IECore.IntData( 10 ) )

		with IECoreArnold.UniverseBlock( writable = True ) :

			n = IECoreArnold.NodeAlgo.convert( p )
			self.assertEqual( arnold.AiNodeGetInt( n, "myPrimVar" ), 10 )
	def testConstantPrimitiveVariable( self ) :
	
		p = IECore.PointsPrimitive( IECore.V3fVectorData( 10 ) )
		p["myPrimVar"] = IECore.PrimitiveVariable( IECore.PrimitiveVariable.Interpolation.Constant, IECore.IntData( 10 ) )
		
		with IECoreArnold.UniverseBlock() :

			n = IECoreArnold.ToArnoldPointsConverter( p ).convert()
			self.assertEqual( arnold.AiNodeGetInt( n, "user:myPrimVar" ), 10 )
示例#8
0
    def testResolution(self):

        s = Gaffer.ScriptNode()

        s["camera"] = GafferScene.Camera()

        s["options"] = GafferScene.StandardOptions()
        s["options"]["in"].setInput(s["camera"]["out"])
        s["options"]["options"]["renderResolution"]["enabled"].setValue(True)
        s["options"]["options"]["renderResolution"]["value"].setValue(
            imath.V2i(200, 100))
        s["options"]["options"]["resolutionMultiplier"]["enabled"].setValue(
            True)
        s["options"]["options"]["resolutionMultiplier"]["value"].setValue(2)

        s["render"] = GafferArnold.ArnoldRender()
        s["render"]["in"].setInput(s["options"]["out"])
        s["render"]["mode"].setValue(s["render"].Mode.SceneDescriptionMode)
        s["render"]["fileName"].setValue(self.temporaryDirectory() +
                                         "/test.ass")

        # Default camera should have the right resolution.

        s["render"]["task"].execute()

        with IECoreArnold.UniverseBlock(writable=True):

            arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass")
            options = arnold.AiUniverseGetOptions()
            self.assertEqual(arnold.AiNodeGetInt(options, "xres"), 400)
            self.assertEqual(arnold.AiNodeGetInt(options, "yres"), 200)

        # As should a camera picked from the scene.

        s["options"]["options"]["renderCamera"]["enabled"].setValue(True)
        s["options"]["options"]["renderCamera"]["value"].setValue("/camera")
        s["render"]["task"].execute()

        with IECoreArnold.UniverseBlock(writable=True):

            arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass")
            options = arnold.AiUniverseGetOptions()
            self.assertEqual(arnold.AiNodeGetInt(options, "xres"), 400)
            self.assertEqual(arnold.AiNodeGetInt(options, "yres"), 200)
示例#9
0
    def testConstantPrimitiveVariable(self):

        p = IECoreScene.PointsPrimitive(IECore.V3fVectorData(10))
        p["myPrimVar"] = IECoreScene.PrimitiveVariable(
            IECoreScene.PrimitiveVariable.Interpolation.Constant,
            IECore.IntData(10))

        with IECoreArnold.UniverseBlock(writable=True) as universe:

            n = IECoreArnold.NodeAlgo.convert(p, universe, "testPoints")
            self.assertEqual(arnold.AiNodeGetInt(n, "myPrimVar"), 10)
示例#10
0
    def testBlindData(self):

        flat = IECoreScene.Shader("flat")
        flat.blindData().update({
            "user:testInt":
            IECore.IntData(1),
            "user:testFloat":
            IECore.FloatData(2.5),
            "user:testV3f":
            IECore.V3fData(imath.V3f(1, 2, 3)),
            "user:testColor3f":
            IECore.Color3fData(imath.Color3f(4, 5, 6)),
            "user:testString":
            IECore.StringData("we're all doomed"),
        })

        network = IECoreScene.ShaderNetwork(shaders={
            "noiseHandle":
            IECoreScene.Shader("noise"),
            "flatHandle":
            flat,
        },
                                            connections=[
                                                (("noiseHandle", ""),
                                                 ("flatHandle", "color")),
                                            ],
                                            output="flatHandle")

        with IECoreArnold.UniverseBlock(writable=True) as universe:

            nodes = IECoreArnoldPreview.ShaderNetworkAlgo.convert(
                network, universe, "test")

            self.assertEqual(len(nodes), 2)
            self.assertEqual(
                arnold.AiNodeEntryGetName(arnold.AiNodeGetNodeEntry(nodes[0])),
                "noise")
            self.assertEqual(
                arnold.AiNodeEntryGetName(arnold.AiNodeGetNodeEntry(nodes[1])),
                "flat")

            self.assertEqual(arnold.AiNodeGetName(nodes[0]),
                             "test:noiseHandle")
            self.assertEqual(arnold.AiNodeGetName(nodes[1]), "test")

            self.assertEqual(arnold.AiNodeGetInt(nodes[1], "user:testInt"), 1)
            self.assertEqual(arnold.AiNodeGetFlt(nodes[1], "user:testFloat"),
                             2.5)
            self.assertEqual(arnold.AiNodeGetVec(nodes[1], "user:testV3f"),
                             arnold.AtVector(1, 2, 3))
            self.assertEqual(arnold.AiNodeGetRGB(nodes[1], "user:testColor3f"),
                             arnold.AtRGB(4, 5, 6))
            self.assertEqual(arnold.AiNodeGetStr(nodes[1], "user:testString"),
                             "we're all doomed")
示例#11
0
    def testCropWindow(self):

        r = GafferScene.Private.IECoreScenePreview.Renderer.create(
            "IECoreArnold::Renderer", GafferScene.Private.IECoreScenePreview.
            Renderer.RenderType.SceneDescription,
            self.temporaryDirectory() + "/test.ass")

        r.camera(
            "testCamera",
            IECore.Camera(
                parameters={
                    "resolution": IECore.V2i(2000, 1000),
                    "cropWindow": IECore.Box2f(IECore.V2f(0),
                                               IECore.V2f(1, 0.75)),
                }))

        r.option("camera", IECore.StringData("testCamera"))

        r.render()
        del r

        with IECoreArnold.UniverseBlock():

            arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass")
            options = arnold.AiUniverseGetOptions()

            self.assertEqual(arnold.AiNodeGetInt(options, "xres"), 2000)
            self.assertEqual(arnold.AiNodeGetInt(options, "yres"), 1000)

            self.assertEqual(arnold.AiNodeGetInt(options, "region_min_x"), 0)
            self.assertEqual(arnold.AiNodeGetInt(options, "region_min_y"), 0)
            self.assertEqual(arnold.AiNodeGetInt(options, "region_max_x"),
                             1999)
            self.assertEqual(arnold.AiNodeGetInt(options, "region_max_y"), 749)
示例#12
0
def Init(procName):
    proc = arnold.AiNodeLookUpByName(procName)
    if not proc:
        print("No such procedural: %s" % procName)
        return (0, None)

    attrs = {}

    it = arnold.AiNodeGetUserParamIterator(proc)

    while not arnold.AiUserParamIteratorFinished(it):
        param = arnold.AiUserParamIteratorGetNext(it)
        pname = arnold.AiUserParamGetName(param)
        pcat = arnold.AiUserParamGetCategory(param)
        if pcat == arnold.AI_USERDEF_CONSTANT:
            ptype = arnold.AiUserParamGetType(param)
            pval = None
            if ptype == arnold.AI_TYPE_BOOLEAN:
                pval = arnold.AiNodeGetBool(proc, pname)
            elif ptype == arnold.AI_TYPE_INT:
                pval = arnold.AiNodeGetInt(proc, pname)
            elif ptype == arnold.AI_TYPE_UINT:
                pval = arnold.AiNodeGetUInt(proc, pname)
            elif ptype == arnold.AI_TYPE_FLOAT:
                pval = arnold.AiNodeGetFlt(proc, pname)
            elif ptype == arnold.AI_TYPE_POINT:
                pval = arnold.AiNodeGetPnt(proc, pname)
            elif ptype == arnold.AI_TYPE_POINT2:
                pval = arnold.AiNodeGetPnt2(proc, pname)
            elif ptype == arnold.AI_TYPE_VECTOR:
                pval = arnold.AiNodeGetVec(proc, pname)
            elif ptype == arnold.AI_TYPE_RGB:
                pval = arnold.AiNodeGetRGB(proc, pname)
            elif ptype == arnold.AI_TYPE_RGBA:
                pval = arnold.AiNodeGetRGBA(proc, pname)
            elif ptype == arnold.AI_TYPE_STRING:
                pval = arnold.AiNodeGetStr(proc, pname)
            if pval != None:
                attrs[pname] = (ptype, pval)
            else:
                print("Unsupported type (%d) for parameter \"%s\"" %
                      (ptype, pname))
        else:
            print("Ignore non constant parameter \"%s\"" % pname)

    arnold.AiUserParamIteratorFinished(it)

    return (1, attrs)
示例#13
0
	def testRenderRegion( self ) :

		s = Gaffer.ScriptNode()

		s["camera"] = GafferScene.Camera()

		s["options"] = GafferScene.StandardOptions()
		s["options"]["in"].setInput( s["camera"]["out"] )
		s["options"]["options"]["renderCamera"]["enabled"].setValue( True )
		s["options"]["options"]["renderCamera"]["value"].setValue( "/camera" )

		s["render"] = GafferArnold.ArnoldRender()
		s["render"]["in"].setInput( s["options"]["out"] )
		s["render"]["mode"].setValue( s["render"].Mode.SceneDescriptionMode )
		s["render"]["fileName"].setValue( self.temporaryDirectory() + "/test.ass" )

		# Default region
		s["render"]["task"].execute()

		with IECoreArnold.UniverseBlock( writable = True ) :

			arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" )
			options = arnold.AiUniverseGetOptions()
			self.assertEqual( arnold.AiNodeGetInt( options, "xres" ), 640 )
			self.assertEqual( arnold.AiNodeGetInt( options, "yres" ), 480 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_x" ), 0 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_x" ), 639 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_y" ), 0 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_y" ), 479 )

		# Apply Crop Window
		s["options"]["options"]["renderCropWindow"]["enabled"].setValue( True )
		s["options"]["options"]["renderCropWindow"]["value"].setValue( imath.Box2f( imath.V2f( 0.25, 0.5 ), imath.V2f( 0.75, 1.0 ) ) )

		s["render"]["task"].execute()

		with IECoreArnold.UniverseBlock( writable = True ) :

			arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" )
			options = arnold.AiUniverseGetOptions()
			self.assertEqual( arnold.AiNodeGetInt( options, "xres" ), 640 )
			self.assertEqual( arnold.AiNodeGetInt( options, "yres" ), 480 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_x" ), 160 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_x" ), 479 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_y" ), 240 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_y" ), 479 )

		# Test Empty Crop Window
		s["options"]["options"]["renderCropWindow"]["value"].setValue( imath.Box2f() )

		s["render"]["task"].execute()

		with IECoreArnold.UniverseBlock( writable = True ) :

			arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" )
			options = arnold.AiUniverseGetOptions()
			self.assertEqual( arnold.AiNodeGetInt( options, "xres" ), 640 )
			self.assertEqual( arnold.AiNodeGetInt( options, "yres" ), 480 )

			# Since Arnold doesn't support empty regions, we default to one pixel in the corner
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_x" ), 0 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_x" ), 0 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_y" ), 479 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_y" ), 479 )

		# Apply Overscan
		s["options"]["options"]["renderCropWindow"]["enabled"].setValue( False )
		s["options"]["options"]["overscan"]["enabled"].setValue( True )
		s["options"]["options"]["overscan"]["value"].setValue( True )
		s["options"]["options"]["overscanTop"]["enabled"].setValue( True )
		s["options"]["options"]["overscanTop"]["value"].setValue( 0.1 )
		s["options"]["options"]["overscanBottom"]["enabled"].setValue( True )
		s["options"]["options"]["overscanBottom"]["value"].setValue( 0.2 )
		s["options"]["options"]["overscanLeft"]["enabled"].setValue( True )
		s["options"]["options"]["overscanLeft"]["value"].setValue( 0.3 )
		s["options"]["options"]["overscanRight"]["enabled"].setValue( True )
		s["options"]["options"]["overscanRight"]["value"].setValue( 0.4 )

		s["render"]["task"].execute()

		with IECoreArnold.UniverseBlock( writable = True ) :

			arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" )
			options = arnold.AiUniverseGetOptions()
			self.assertEqual( arnold.AiNodeGetInt( options, "xres" ), 640 )
			self.assertEqual( arnold.AiNodeGetInt( options, "yres" ), 480 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_x" ), -192 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_x" ), 640 + 255 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_y" ), -48 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_y" ), 480 + 95 )
示例#14
0
    def get_int(self, param):
        if not self.is_valid():
            return None

        return arnold.AiNodeGetInt(self.data, param)
示例#15
0
    def testUpdate(self):

        network = IECoreScene.ShaderNetwork(shaders={
            "noiseHandle":
            IECoreScene.Shader("noise"),
            "flatHandle":
            IECoreScene.Shader("flat"),
        },
                                            connections=[
                                                (("noiseHandle", ""),
                                                 ("flatHandle", "color")),
                                            ],
                                            output="flatHandle")

        with IECoreArnold.UniverseBlock(writable=True):

            # Convert

            nodes = IECoreArnoldPreview.ShaderNetworkAlgo.convert(
                network, "test")

            def assertNoiseAndFlatNodes():

                self.assertEqual(len(nodes), 2)
                self.assertEqual(
                    arnold.AiNodeEntryGetName(
                        arnold.AiNodeGetNodeEntry(nodes[0])), "noise")
                self.assertEqual(
                    arnold.AiNodeEntryGetName(
                        arnold.AiNodeGetNodeEntry(nodes[1])), "flat")

                self.assertEqual(arnold.AiNodeGetName(nodes[0]),
                                 "test:noiseHandle")
                self.assertEqual(arnold.AiNodeGetName(nodes[1]), "test")

                self.assertEqual(
                    ctypes.addressof(
                        arnold.AiNodeGetLink(nodes[1], "color").contents),
                    ctypes.addressof(nodes[0].contents))

            assertNoiseAndFlatNodes()

            # Convert again with no changes at all. We want to see the same nodes reused.

            originalNodes = nodes[:]
            self.assertTrue(
                IECoreArnoldPreview.ShaderNetworkAlgo.update(nodes, network))
            assertNoiseAndFlatNodes()

            self.assertEqual(ctypes.addressof(nodes[0].contents),
                             ctypes.addressof(originalNodes[0].contents))
            self.assertEqual(ctypes.addressof(nodes[1].contents),
                             ctypes.addressof(originalNodes[1].contents))

            # Convert again with a tweak to a noise parameter. We want to see the same nodes
            # reused, with the new parameter value taking hold.

            noise = network.getShader("noiseHandle")
            noise.parameters["octaves"] = IECore.IntData(3)
            network.setShader("noiseHandle", noise)

            originalNodes = nodes[:]
            self.assertTrue(
                IECoreArnoldPreview.ShaderNetworkAlgo.update(nodes, network))
            assertNoiseAndFlatNodes()

            self.assertEqual(ctypes.addressof(nodes[0].contents),
                             ctypes.addressof(originalNodes[0].contents))
            self.assertEqual(ctypes.addressof(nodes[1].contents),
                             ctypes.addressof(originalNodes[1].contents))
            self.assertEqual(arnold.AiNodeGetInt(nodes[0], "octaves"), 3)

            # Remove the noise shader, and replace it with an image. Make sure the new network is as we expect, and
            # the old noise node has been destroyed.

            network.removeShader("noiseHandle")
            network.setShader("imageHandle", IECoreScene.Shader("image"))
            network.addConnection(
                (("imageHandle", ""), ("flatHandle", "color")))

            originalNodes = nodes[:]
            self.assertTrue(
                IECoreArnoldPreview.ShaderNetworkAlgo.update(nodes, network))

            self.assertEqual(ctypes.addressof(nodes[1].contents),
                             ctypes.addressof(originalNodes[1].contents))

            self.assertEqual(
                arnold.AiNodeEntryGetName(arnold.AiNodeGetNodeEntry(nodes[0])),
                "image")
            self.assertEqual(
                arnold.AiNodeEntryGetName(arnold.AiNodeGetNodeEntry(nodes[1])),
                "flat")

            self.assertEqual(arnold.AiNodeGetName(nodes[0]),
                             "test:imageHandle")
            self.assertEqual(arnold.AiNodeGetName(nodes[1]), "test")

            self.assertEqual(
                ctypes.addressof(
                    arnold.AiNodeGetLink(nodes[1], "color").contents),
                ctypes.addressof(nodes[0].contents))

            self.assertIsNone(arnold.AiNodeLookUpByName("test:noiseHandle"))

            # Replace the output shader with something else.

            network.removeShader("flatHandle")
            network.setShader("lambertHandle", IECoreScene.Shader("lambert"))
            network.addConnection(
                (("imageHandle", ""), ("lambertHandle", "Kd_color")))
            network.setOutput(("lambertHandle", ""))

            originalNodes = nodes[:]
            self.assertFalse(
                IECoreArnoldPreview.ShaderNetworkAlgo.update(nodes, network))

            self.assertEqual(ctypes.addressof(nodes[0].contents),
                             ctypes.addressof(originalNodes[0].contents))

            self.assertEqual(
                arnold.AiNodeEntryGetName(arnold.AiNodeGetNodeEntry(nodes[0])),
                "image")
            self.assertEqual(
                arnold.AiNodeEntryGetName(arnold.AiNodeGetNodeEntry(nodes[1])),
                "lambert")

            self.assertEqual(arnold.AiNodeGetName(nodes[0]),
                             "test:imageHandle")
            self.assertEqual(arnold.AiNodeGetName(nodes[1]), "test")

            self.assertEqual(
                ctypes.addressof(
                    arnold.AiNodeGetLink(nodes[1], "Kd_color").contents),
                ctypes.addressof(nodes[0].contents))