def _headerWidget(self): with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal) as result: collapseButton = GafferUI.Button(image="collapsibleArrowRight.png", hasFrame=False) self.__collapseButtonConnection = collapseButton.clickedSignal( ).connect(Gaffer.WeakMethod(self.__collapseButtonClicked)) GafferUI.Spacer(imath.V2i(2)) # find parameters which belong in the header ############################################ preHeaderParameters = [] headerParameters = [] for parameter in self.__parameterHandler.parameter().values(): with IECore.IgnoredExceptions(KeyError): if parameter.userData( )["UI"]["classVectorParameterPreHeader"].value: preHeaderParameters.append(parameter) with IECore.IgnoredExceptions(KeyError): if parameter.userData( )["UI"]["classVectorParameterHeader"].value: headerParameters.append(parameter) # make the header ################# # things before the layer button for parameter in preHeaderParameters: GafferCortexUI.ParameterValueWidget.create( self.__parameterHandler.childParameterHandler(parameter)) # the layer button layerButton = GafferUI.MenuButton( image="classVectorParameterHandle.png", hasFrame=False) compoundPlugValueWidget = self.ancestor(_PlugValueWidget) parentParameter = compoundPlugValueWidget._parameter() cls = parentParameter.getClass( self.__parameterHandler.parameter().name, True) layerButtonToolTip = "<h3>%s v%d</h3>" % (cls[1], cls[2]) if cls[0].description: layerButtonToolTip += "<p>%s</p>" % cls[0].description layerButtonToolTip += "<p>Click to reorder or remove.</p>" layerButton.setToolTip(layerButtonToolTip) layerButton.setMenu( GafferUI.Menu( IECore.curry( Gaffer.WeakMethod( compoundPlugValueWidget._layerMenuDefinition), self.__parameterHandler.parameter().name))) GafferUI.Spacer(imath.V2i(2)) # the label if "label" in self.getPlug(): self.__label = GafferUI.Label( self.getPlug()["label"].getValue(), horizontalAlignment=GafferUI.Label.HorizontalAlignment.Left ) self.__label._qtWidget().setFixedWidth( GafferUI.PlugWidget.labelWidth()) ## \todo Naughty! self.__label.setToolTip( compoundPlugValueWidget._parameterToolTip( self.__parameterHandler.childParameterHandler( self.__parameterHandler.parameter()["label"]), ), ) self.__labelButtonPressConnection = self.__label.buttonPressSignal( ).connect(Gaffer.WeakMethod(self.__labelButtonPress)) self.__plugSetConnection = self.getPlug().node().plugSetSignal( ).connect(Gaffer.WeakMethod(self.__plugSet)) # parameters after the label for parameter in headerParameters: GafferCortexUI.ParameterValueWidget.create( self.__parameterHandler.childParameterHandler(parameter)) # prevent things expanding in an unwanted way GafferUI.Spacer(imath.V2i(1), imath.V2i(999999, 1), parenting={"expand": True}) return result
def testCacheReuse(self): # Send an image to the catalogue, and also # capture the display driver that we used to # send it. c = GafferImage.Catalogue() c["directory"].setValue( os.path.join(self.temporaryDirectory(), "catalogue")) drivers = GafferTest.CapturingSlot( GafferImage.Display.driverCreatedSignal()) r = GafferImage.ImageReader() r["fileName"].setValue( "${GAFFER_ROOT}/python/GafferImageTest/images/checker.exr") self.sendImage(r["out"], c) self.assertEqual(len(drivers), 1) # The image will have been saved to disk so it can persist between sessions, # and the Catalogue should have dropped any reference it has to the driver, # in order to save memory. self.assertEqual(len(c["images"]), 1) self.assertEqual( os.path.dirname(c["images"][0]["fileName"].getValue()), c["directory"].getValue()) self.assertEqual(drivers[0][0].refCount(), 1) # But we don't want the Catalogue to immediately reload the image from # disk, because for large images with many AOVs this is a huge overhead. # We want to temporarily reuse the cache entries that were created from # the data in the display driver. These should be identical to a regular # Display node containing the same driver. display = GafferImage.Display() display.setDriver(drivers[0][0]) self.assertEqual(display["out"].channelDataHash("R", imath.V2i(0)), c["out"].channelDataHash("R", imath.V2i(0))) self.assertTrue(display["out"].channelData( "R", imath.V2i(0), _copy=False).isSame(c["out"].channelData("R", imath.V2i(0), _copy=False))) # This applies to copies too c["images"].addChild( GafferImage.Catalogue.Image(flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) self.assertEqual(len(c["images"]), 2) c["images"][1].copyFrom(c["images"][0]) c["imageIndex"].setValue(1) self.assertEqual(display["out"].channelDataHash("R", imath.V2i(0)), c["out"].channelDataHash("R", imath.V2i(0))) self.assertTrue(display["out"].channelData( "R", imath.V2i(0), _copy=False).isSame(c["out"].channelData("R", imath.V2i(0), _copy=False)))
def getPosition(self): return imath.V2i(self._qtWidget().x(), self._qtWidget().y())
def testOldRandomCamera(self): random.seed(42) with IECoreArnold.UniverseBlock(writable=True): for i in range(40): resolution = imath.V2i(random.randint(10, 1000), random.randint(10, 1000)) pixelAspectRatio = random.uniform(0.5, 2) screenWindow = imath.Box2f( imath.V2f(-random.uniform(0, 2), -random.uniform(0, 2)), imath.V2f(random.uniform(0, 2), random.uniform(0, 2))) screenWindowAspectScale = imath.V2f( 1.0, (screenWindow.size()[0] / screenWindow.size()[1]) * (resolution[1] / float(resolution[0])) / pixelAspectRatio) screenWindow.setMin(screenWindow.min() * screenWindowAspectScale) screenWindow.setMax(screenWindow.max() * screenWindowAspectScale) c = IECoreScene.Camera( parameters={ "projection": "orthographic" if random.random() > 0.5 else "perspective", "projection:fov": random.uniform(1, 100), "clippingPlanes": imath.V2f(random.uniform(0.001, 100)) + imath.V2f(0, random.uniform(0, 1000)), "resolution": resolution, "pixelAspectRatio": pixelAspectRatio }) if i < 20: c.parameters()["screenWindow"] = screenWindow n = IECoreArnold.NodeAlgo.convert(c, "testCamera") arnoldType = "persp_camera" if c.parameters()["projection"].value == "orthographic": arnoldType = "ortho_camera" self.assertEqual( arnold.AiNodeEntryGetName(arnold.AiNodeGetNodeEntry(n)), arnoldType) cortexClip = c.parameters()["clippingPlanes"].value self.assertEqual(arnold.AiNodeGetFlt(n, "near_clip"), cortexClip[0]) self.assertEqual(arnold.AiNodeGetFlt(n, "far_clip"), cortexClip[1]) resolution = c.parameters()["resolution"].value aspect = c.parameters( )["pixelAspectRatio"].value * resolution.x / float( resolution.y) if "screenWindow" in c.parameters(): cortexWindow = c.parameters()["screenWindow"].value else: if aspect > 1.0: cortexWindow = imath.Box2f(imath.V2f(-aspect, -1), imath.V2f(aspect, 1)) else: cortexWindow = imath.Box2f(imath.V2f(-1, -1 / aspect), imath.V2f(1, 1 / aspect)) if c.parameters()["projection"].value != "orthographic": windowScale = math.tan( math.radians(0.5 * arnold.AiNodeGetFlt(n, "fov"))) cortexWindowScale = math.tan( math.radians(0.5 * c.parameters()["projection:fov"].value)) else: windowScale = 1.0 cortexWindowScale = 1.0 self.assertAlmostEqual( windowScale * arnold.AiNodeGetVec2(n, "screen_window_min").x, cortexWindowScale * cortexWindow.min()[0], places=4) self.assertAlmostEqual( windowScale * arnold.AiNodeGetVec2(n, "screen_window_min").y, cortexWindowScale * cortexWindow.min()[1] * aspect, places=4) self.assertAlmostEqual( windowScale * arnold.AiNodeGetVec2(n, "screen_window_max").x, cortexWindowScale * cortexWindow.max()[0], places=4) self.assertAlmostEqual( windowScale * arnold.AiNodeGetVec2(n, "screen_window_max").y, cortexWindowScale * cortexWindow.max()[1] * aspect, places=4) if c.parameters()["projection"].value == "perspective": self.assertAlmostEqual( arnold.AiNodeGetVec2(n, "screen_window_max").x - arnold.AiNodeGetVec2(n, "screen_window_min").x, 2.0, places=6) self.assertAlmostEqual( arnold.AiNodeGetVec2(n, "screen_window_max").y - arnold.AiNodeGetVec2(n, "screen_window_min").y, 2.0, places=6)
def testManyImages(self): allFilter = GafferScene.PathFilter() allFilter["paths"].setValue(IECore.StringVectorData(['/...'])) sphere = GafferScene.Sphere() sphere["transform"]["translate"].setValue(imath.V3f(-3, 0, 0)) standardSurface = GafferArnold.ArnoldShader() standardSurface.loadShader("standard_surface") shaderAssignment = GafferScene.ShaderAssignment() shaderAssignment["in"].setInput(sphere["out"]) shaderAssignment["filter"].setInput(allFilter["out"]) shaderAssignment["shader"].setInput(standardSurface["out"]) uvScaleCode = GafferOSL.OSLCode() uvScaleCode["out"].addChild( Gaffer.V3fPlug("uvScaled", direction=Gaffer.Plug.Direction.Out)) uvScaleCode["code"].setValue('uvScaled = vector( u * 2, v * 2, 0 );') outUV = GafferOSL.OSLShader() outUV.loadShader("ObjectProcessing/OutUV") outUV["parameters"]["value"].setInput(uvScaleCode["out"]["uvScaled"]) outObject2 = GafferOSL.OSLShader() outObject2.loadShader("ObjectProcessing/OutObject") outObject2["parameters"]["in0"].setInput( outUV["out"]["primitiveVariable"]) uvScaleOSL = GafferOSL.OSLObject() uvScaleOSL["in"].setInput(shaderAssignment["out"]) uvScaleOSL["filter"].setInput(allFilter["out"]) uvScaleOSL["shader"].setInput(outObject2["out"]) uvScaleOSL["interpolation"].setValue(5) mapOffset = GafferScene.MapOffset() mapOffset["in"].setInput(uvScaleOSL["out"]) mapOffset["filter"].setInput(allFilter["out"]) mapOffset["udim"].setValue(1033) offsetGroup = GafferScene.Group() offsetGroup["in"]["in0"].setInput(mapOffset["out"]) offsetGroup["name"].setValue('offset') offsetGroup["transform"]["translate"].setValue(imath.V3f(6, 0, 3)) combineGroup = GafferScene.Group() combineGroup["in"]["in0"].setInput(uvScaleOSL["out"]) combineGroup["in"]["in1"].setInput(offsetGroup["out"]) lights = [] for color, rotate in [((1, 0, 0), (0, 0, 0)), ((0, 1, 0), (0, 90, 0)), ((0, 0, 1), (-90, 0, 0))]: light = GafferArnold.ArnoldLight() light.loadShader("distant_light") light["parameters"]["color"].setValue(imath.Color3f(*color)) light["transform"]["rotate"].setValue(imath.V3f(*rotate)) combineGroup["in"][-1].setInput(light["out"]) lights.append(light) arnoldTextureBake = GafferArnold.ArnoldTextureBake() arnoldTextureBake["in"].setInput(combineGroup["out"]) arnoldTextureBake["filter"].setInput(allFilter["out"]) arnoldTextureBake["bakeDirectory"].setValue(self.temporaryDirectory() + '/bakeSpheres/') arnoldTextureBake["defaultResolution"].setValue(32) arnoldTextureBake["aovs"].setValue('beauty:RGBA diffuse:diffuse') arnoldTextureBake["tasks"].setValue(3) arnoldTextureBake["cleanupIntermediateFiles"].setValue(True) # Dispatch the bake script = Gaffer.ScriptNode() script.addChild(arnoldTextureBake) dispatcher = GafferDispatch.LocalDispatcher() dispatcher["jobsDirectory"].setValue(self.temporaryDirectory()) dispatcher.dispatch([arnoldTextureBake]) # Test that we are writing all expected files, and that we have cleaned up all temp files expectedUdims = [i + j for j in [1001, 1033] for i in [0, 1, 10, 11]] self.assertEqual( sorted(os.listdir(self.temporaryDirectory() + '/bakeSpheres/')), ["beauty", "diffuse"]) self.assertEqual( sorted( os.listdir(self.temporaryDirectory() + '/bakeSpheres/beauty')), ["beauty.%i.tx" % i for i in expectedUdims]) self.assertEqual( sorted( os.listdir(self.temporaryDirectory() + '/bakeSpheres/diffuse')), ["diffuse.%i.tx" % i for i in expectedUdims]) # Read back in the 4 udim tiles of a sphere reader = GafferImage.ImageReader() imageTransform = GafferImage.ImageTransform() imageTransform["in"].setInput(reader["out"]) exprBox = Gaffer.Box() expression = Gaffer.Expression() exprBox.addChild(reader) exprBox.addChild(imageTransform) exprBox.addChild(expression) expression.setExpression( inspect.cleandoc( """ i = context.get( "loop:index", 0 ) layer = context.get( "collect:layerName", "beauty" ) x = i % 2 y = i / 2 parent["ImageReader"]["fileName"] = '""" + self.temporaryDirectory() + """/bakeSpheres/%s/%s.%i.tx' % ( layer, layer, 1001 + x + y * 10 ) parent["ImageTransform"]["transform"]["translate"] = imath.V2f( 32 * x, 32 * y ) """), "python") udimLoop = Gaffer.Loop() udimLoop.setup(GafferImage.ImagePlug()) udimLoop["iterations"].setValue(4) udimMerge = GafferImage.Merge() udimMerge["in"]["in0"].setInput(imageTransform["out"]) udimMerge["in"]["in1"].setInput(udimLoop["previous"]) udimLoop["next"].setInput(udimMerge["out"]) aovCollect = GafferImage.CollectImages() aovCollect["in"].setInput(udimLoop["out"]) aovCollect["rootLayers"].setValue( IECore.StringVectorData(['beauty', 'diffuse'])) # We have a little reference image for how the diffuse should look imageReaderRef = GafferImage.ImageReader() imageReaderRef["fileName"].setValue( os.path.dirname(__file__) + "/images/sphereLightBake.exr") resizeRef = GafferImage.Resize() resizeRef["in"].setInput(imageReaderRef["out"]) resizeRef["format"].setValue(GafferImage.Format(64, 64, 1.000)) shuffleRef = GafferImage.Shuffle() shuffleRef["in"].setInput(resizeRef["out"]) for layer in ["beauty", "diffuse"]: for channel in ["R", "G", "B"]: shuffleRef["channels"].addChild( GafferImage.Shuffle.ChannelPlug()) shuffleRef["channels"][-1]["in"].setValue(channel) shuffleRef["channels"][-1]["out"].setValue(layer + "." + channel) differenceMerge = GafferImage.Merge() differenceMerge["in"]["in0"].setInput(aovCollect["out"]) differenceMerge["in"]["in1"].setInput(shuffleRef["out"]) differenceMerge["operation"].setValue( GafferImage.Merge.Operation.Difference) stats = GafferImage.ImageStats() stats["in"].setInput(differenceMerge["out"]) stats["area"].setValue(imath.Box2i(imath.V2i(0, 0), imath.V2i(64, 64))) # We should get a very close match to our single tile low res reference bake stats["channels"].setValue( IECore.StringVectorData( ['diffuse.R', 'diffuse.G', 'diffuse.B', 'diffuse.A'])) for i in range(3): self.assertLess(stats["average"].getValue()[i], 0.002) self.assertLess(stats["max"].getValue()[i], 0.02) # The beauty should be mostly a close match, but with a high max difference due to the spec pings stats["channels"].setValue( IECore.StringVectorData( ['beauty.R', 'beauty.G', 'beauty.B', 'beauty.A'])) for i in range(3): self.assertLess(stats["average"].getValue()[i], 0.1) self.assertGreater(stats["max"].getValue()[i], 0.3)
def points(self): pData = IECore.V3fVectorData([ imath.V3f(0, 1, 2), imath.V3f(1), imath.V3f(2), imath.V3f(3), imath.V3f(4), imath.V3f(5), imath.V3f(6), imath.V3f(7), imath.V3f(8), imath.V3f(9), imath.V3f(10), imath.V3f(11), ]) points = IECoreScene.PointsPrimitive(pData) floatData = IECore.FloatData(1.5) v2fData = IECore.V2fData(imath.V2f(1.5, 2.5)) v3fData = IECore.V3fData(imath.V3f(1.5, 2.5, 3.5)) color3fData = IECore.Color3fData(imath.Color3f(1.5, 2.5, 3.5)) intData = IECore.IntData(1) v2iData = IECore.V2iData(imath.V2i(1, 2)) v3iData = IECore.V3iData(imath.V3i(1, 2, 3)) stringData = IECore.StringData("this is a string") intRange = range(1, 13) floatVectorData = IECore.FloatVectorData([x + 0.5 for x in intRange]) v2fVectorData = IECore.V2fVectorData( [imath.V2f(x, x + 0.5) for x in intRange]) v3fVectorData = IECore.V3fVectorData( [imath.V3f(x, x + 0.5, x + 0.75) for x in intRange]) color3fVectorData = IECore.Color3fVectorData( [imath.Color3f(x, x + 0.5, x + 0.75) for x in intRange]) intVectorData = IECore.IntVectorData(intRange) v2iVectorData = IECore.V2iVectorData( [imath.V2i(x, -x) for x in intRange]) v3iVectorData = IECore.V3iVectorData( [imath.V3i(x, -x, x * 2) for x in intRange]) stringVectorData = IECore.StringVectorData( ["string number %d!" % x for x in intRange]) detailInterpolation = IECoreScene.PrimitiveVariable.Interpolation.Constant pointInterpolation = IECoreScene.PrimitiveVariable.Interpolation.Vertex # add all valid detail attrib types points["floatDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, floatData) points["v2fDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, v2fData) points["v3fDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, v3fData) points["color3fDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, color3fData) points["intDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, intData) points["v2iDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, v2iData) points["v3iDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, v3iData) points["stringDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, stringData) # add all valid point attrib types points["floatPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, floatVectorData) points["v2fPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, v2fVectorData) points["v3fPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, v3fVectorData) points["color3fPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, color3fVectorData) points["intPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, intVectorData) points["v2iPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, v2iVectorData) points["v3iPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, v3iVectorData) points["stringPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, stringVectorData, IECore.IntVectorData(range(0, 12))) points.blindData()['name'] = "pointsGroup" return points
def __init__(self, name="ArnoldTextureBake"): GafferDispatch.TaskNode.__init__(self, name) self["in"] = GafferScene.ScenePlug() self["filter"] = GafferScene.FilterPlug() self["bakeDirectory"] = Gaffer.StringPlug("bakeDirectory", defaultValue="") self["defaultFileName"] = Gaffer.StringPlug( "defaultFileName", defaultValue="${bakeDirectory}/<AOV>/<AOV>.<UDIM>.exr") self["defaultResolution"] = Gaffer.IntPlug("defaultResolution", defaultValue=512) self["uvSet"] = Gaffer.StringPlug("uvSet", defaultValue='uv') self["normalOffset"] = Gaffer.FloatPlug("offset", defaultValue=0.1) self["aovs"] = Gaffer.StringPlug("aovs", defaultValue='beauty:RGBA') self["tasks"] = Gaffer.IntPlug("tasks", defaultValue=1) self["cleanupIntermediateFiles"] = Gaffer.BoolPlug( "cleanupIntermediateFiles", defaultValue=True) self["applyMedianFilter"] = Gaffer.BoolPlug("applyMedianFilter", Gaffer.Plug.Direction.In, False) self["medianRadius"] = Gaffer.IntPlug("medianRadius", Gaffer.Plug.Direction.In, 1) # Set up connection to preTasks beforehand self["__PreTaskList"] = GafferDispatch.TaskList() self["__PreTaskList"]["preTasks"].setInput(self["preTasks"]) self["__CleanPreTasks"] = Gaffer.DeleteContextVariables() self["__CleanPreTasks"].setup(GafferDispatch.TaskNode.TaskPlug()) self["__CleanPreTasks"]["in"].setInput(self["__PreTaskList"]["task"]) self["__CleanPreTasks"]["variables"].setValue( "BAKE_WEDGE:index BAKE_WEDGE:value_unused") # First, setup python commands which will dispatch a chunk of a render or image tasks as # immediate execution once they reach the farm - this allows us to run multiple tasks in # one farm process. self["__RenderDispatcher"] = GafferDispatch.PythonCommand() self["__RenderDispatcher"]["preTasks"][0].setInput( self["__CleanPreTasks"]["out"]) self["__RenderDispatcher"]["command"].setValue( inspect.cleandoc(""" import GafferDispatch # We need to access frame and "BAKE_WEDGE:index" so that the hash of render varies with the wedge index, # so we might as well print what we're doing IECore.msg( IECore.MessageHandler.Level.Info, "Bake Process", "Dispatching render task index %i for frame %i" % ( context["BAKE_WEDGE:index"], context.getFrame() ) ) d = GafferDispatch.LocalDispatcher() d.dispatch( [ self.parent()["__bakeDirectoryContext"] ] ) """)) self["__ImageDispatcher"] = GafferDispatch.PythonCommand() self["__ImageDispatcher"]["preTasks"][0].setInput( self["__RenderDispatcher"]["task"]) self["__ImageDispatcher"]["command"].setValue( inspect.cleandoc(""" import GafferDispatch # We need to access frame and "BAKE_WEDGE:index" so that the hash of render varies with the wedge index, # so we might as well print what we're doing IECore.msg( IECore.MessageHandler.Level.Info, "Bake Process", "Dispatching image task index %i for frame %i" % ( context["BAKE_WEDGE:index"], context.getFrame() ) ) d = GafferDispatch.LocalDispatcher() d.dispatch( [ self.parent()["__CleanUpSwitch"] ] ) """)) # Connect through the dispatch settings to the render dispatcher # ( The image dispatcher runs much quicker, and should be OK using default settings ) self["__RenderDispatcher"]["dispatcher"].setInput(self["dispatcher"]) # Set up variables so the dispatcher knows that the render and image dispatches depend on # the file paths ( in case they are varying in a wedge ) for redispatch in [ self["__RenderDispatcher"], self["__ImageDispatcher"] ]: redispatch["variables"].addChild( Gaffer.NameValuePlug("bakeDirectory", "", "bakeDirectoryVar")) redispatch["variables"].addChild( Gaffer.NameValuePlug("defaultFileName", "", "defaultFileNameVar")) # Connect the variables via an expression so that get expanded ( this also means that # if you put #### in a filename you will get per frame tasks, because the hash will depend # on frame number ) self["__DispatchVariableExpression"] = Gaffer.Expression() self["__DispatchVariableExpression"].setExpression( inspect.cleandoc(""" parent["__RenderDispatcher"]["variables"]["bakeDirectoryVar"]["value"] = parent["bakeDirectory"] parent["__RenderDispatcher"]["variables"]["defaultFileNameVar"]["value"] = parent["defaultFileName"] parent["__ImageDispatcher"]["variables"]["bakeDirectoryVar"]["value"] = parent["bakeDirectory"] parent["__ImageDispatcher"]["variables"]["defaultFileNameVar"]["value"] = parent["defaultFileName"] """), "python") # Wedge based on tasks into the overall number of tasks to run. Note that we don't know how # much work each task will do until we actually run the render tasks ( this is when scene # expansion happens ). Because we must group all tasks that write to the same file into the # same task batch, if tasks is a large number, some tasks batches could end up empty self["__MainWedge"] = GafferDispatch.Wedge() self["__MainWedge"]["preTasks"][0].setInput( self["__ImageDispatcher"]["task"]) self["__MainWedge"]["variable"].setValue("BAKE_WEDGE:value_unused") self["__MainWedge"]["indexVariable"].setValue("BAKE_WEDGE:index") self["__MainWedge"]["mode"].setValue(1) self["__MainWedge"]["intMin"].setValue(1) self["__MainWedge"]["intMax"].setInput(self["tasks"]) self["task"].setInput(self["__MainWedge"]["task"]) self["task"].setFlags(Gaffer.Plug.Flags.Serialisable, False) # Now set up the render tasks. This involves doing the actual rendering, and triggering the # output of the file list index file. # First get rid of options from the upstream scene that could mess up the bake self["__OptionOverrides"] = GafferScene.StandardOptions() self["__OptionOverrides"]["in"].setInput(self["in"]) self["__OptionOverrides"]["options"]["pixelAspectRatio"][ "enabled"].setValue(True) self["__OptionOverrides"]["options"]["resolutionMultiplier"][ "enabled"].setValue(True) self["__OptionOverrides"]["options"]["overscan"]["enabled"].setValue( True) self["__OptionOverrides"]["options"]["renderCropWindow"][ "enabled"].setValue(True) self["__OptionOverrides"]["options"]["cameraBlur"]["enabled"].setValue( True) self["__OptionOverrides"]["options"]["transformBlur"][ "enabled"].setValue(True) self["__OptionOverrides"]["options"]["deformationBlur"][ "enabled"].setValue(True) self["__CameraSetup"] = self.__CameraSetup() self["__CameraSetup"]["in"].setInput(self["__OptionOverrides"]["out"]) self["__CameraSetup"]["filter"].setInput(self["filter"]) self["__CameraSetup"]["defaultFileName"].setInput( self["defaultFileName"]) self["__CameraSetup"]["defaultResolution"].setInput( self["defaultResolution"]) self["__CameraSetup"]["uvSet"].setInput(self["uvSet"]) self["__CameraSetup"]["aovs"].setInput(self["aovs"]) self["__CameraSetup"]["normalOffset"].setInput(self["normalOffset"]) self["__CameraSetup"]["tasks"].setInput(self["tasks"]) self["__Expression"] = Gaffer.Expression() self["__Expression"].setExpression( 'parent["__CameraSetup"]["taskIndex"] = context.get( "BAKE_WEDGE:index", 0 )', "python") self["__indexFilePath"] = Gaffer.StringPlug() self["__indexFilePath"].setFlags(Gaffer.Plug.Flags.Serialisable, False) self["__IndexFileExpression"] = Gaffer.Expression() self["__IndexFileExpression"].setExpression( inspect.cleandoc(""" import os parent["__indexFilePath"] = os.path.join( parent["bakeDirectory"], "BAKE_FILE_INDEX_" + str( context.get("BAKE_WEDGE:index", 0 ) ) + ".####.txt" ) """), "python") self["__outputIndexCommand"] = Gaffer.PythonCommand() self["__outputIndexCommand"]["variables"].addChild( Gaffer.NameValuePlug("bakeDirectory", Gaffer.StringPlug())) self["__outputIndexCommand"]["variables"][0]["value"].setInput( self["bakeDirectory"]) self["__outputIndexCommand"]["variables"].addChild( Gaffer.NameValuePlug("indexFilePath", Gaffer.StringPlug())) self["__outputIndexCommand"]["variables"][1]["value"].setInput( self["__indexFilePath"]) self["__outputIndexCommand"]["variables"].addChild( Gaffer.NameValuePlug( "fileList", Gaffer.StringVectorDataPlug( defaultValue=IECore.StringVectorData()))) self["__outputIndexCommand"]["variables"][2]["value"].setInput( self["__CameraSetup"]["renderFileList"]) self["__outputIndexCommand"]["command"].setValue( inspect.cleandoc(""" import os import distutils.dir_util # Ensure path exists distutils.dir_util.mkpath( variables["bakeDirectory"] ) f = open( variables["indexFilePath"], "w" ) f.writelines( [ i + "\\n" for i in sorted( variables["fileList"] ) ] ) f.close() IECore.msg( IECore.MessageHandler.Level.Info, "Bake Process", "Wrote list of bake files for this chunk to " + variables["indexFilePath"] ) """)) self["__arnoldRender"] = GafferArnold.ArnoldRender() self["__arnoldRender"]["preTasks"][0].setInput( self["__outputIndexCommand"]["task"]) self["__arnoldRender"]["dispatcher"]["immediate"].setValue(True) self["__arnoldRender"]["in"].setInput(self["__CameraSetup"]["out"]) self["__bakeDirectoryContext"] = GafferDispatch.TaskContextVariables() self["__bakeDirectoryContext"]["variables"].addChild( Gaffer.NameValuePlug("bakeDirectory", Gaffer.StringPlug())) self["__bakeDirectoryContext"]["variables"][0]["value"].setInput( self["bakeDirectory"]) self["__bakeDirectoryContext"]["preTasks"][0].setInput( self["__arnoldRender"]["task"]) # Now set up the image tasks. This involves merging all layers for a UDIM, filling in the # background, writing out this image, converting it to tx, and optionally deleting all the exrs self["__imageList"] = Gaffer.CompoundObjectPlug( "__imageList", defaultValue=IECore.CompoundObject()) self["__imageList"].setFlags(Gaffer.Plug.Flags.Serialisable, False) self["__ImageReader"] = GafferImage.ImageReader() self["__CurInputFileExpression"] = Gaffer.Expression() self["__CurInputFileExpression"].setExpression( inspect.cleandoc(""" l = parent["__imageList"] outFile = context["wedge:outFile"] loopIndex = context[ "loop:index" ] parent["__ImageReader"]["fileName"] = l[outFile][ loopIndex ] """), "python") # Find the max size of any input file self["__SizeLoop"] = Gaffer.LoopComputeNode() self["__SizeLoop"].setup(Gaffer.IntPlug()) self["__SizeMaxExpression"] = Gaffer.Expression() self["__SizeMaxExpression"].setExpression( inspect.cleandoc(""" f = parent["__ImageReader"]["out"]["format"] parent["__SizeLoop"]["next"] = max( f.width(), parent["__SizeLoop"]["previous"] ) """), "python") # Loop over all input files for this output file, and merge them all together self["__ImageLoop"] = Gaffer.LoopComputeNode() self["__ImageLoop"].setup(GafferImage.ImagePlug()) self["__NumInputsForCurOutputExpression"] = Gaffer.Expression() self["__NumInputsForCurOutputExpression"].setExpression( inspect.cleandoc(""" l = parent["__imageList"] outFile = context["wedge:outFile"] numInputs = len( l[outFile] ) parent["__ImageLoop"]["iterations"] = numInputs parent["__SizeLoop"]["iterations"] = numInputs """), "python") self["__Resize"] = GafferImage.Resize() self["__Resize"]["format"]["displayWindow"]["min"].setValue( imath.V2i(0, 0)) self["__Resize"]['format']["displayWindow"]["max"]["x"].setInput( self["__SizeLoop"]["out"]) self["__Resize"]['format']["displayWindow"]["max"]["y"].setInput( self["__SizeLoop"]["out"]) self["__Resize"]['in'].setInput(self["__ImageReader"]["out"]) self["__Merge"] = GafferImage.Merge() self["__Merge"]["in"][0].setInput(self["__Resize"]["out"]) self["__Merge"]["in"][1].setInput(self["__ImageLoop"]["previous"]) self["__Merge"]["operation"].setValue(GafferImage.Merge.Operation.Add) self["__ImageLoop"]["next"].setInput(self["__Merge"]["out"]) # Write out the combined image, so we can immediately read it back in # This is just because we're doing enough image processing that we # could saturate the cache, and Gaffer wouldn't know that this is # the important result to keep self["__ImageIntermediateWriter"] = GafferImage.ImageWriter() self["__ImageIntermediateWriter"]["in"].setInput( self["__ImageLoop"]["out"]) self["__ImageIntermediateReader"] = GafferImage.ImageReader() # Now that we've merged everything together, we can use a BleedFill to fill in the background, # so that texture filtering across the edges will pull in colors that are at least reasonable. self["__BleedFill"] = GafferImage.BleedFill() self["__BleedFill"]["in"].setInput( self["__ImageIntermediateReader"]["out"]) self["__Median"] = GafferImage.Median() self["__Median"]["in"].setInput(self["__BleedFill"]["out"]) self["__Median"]["enabled"].setInput(self["applyMedianFilter"]) self["__Median"]["radius"]["x"].setInput(self["medianRadius"]) self["__Median"]["radius"]["y"].setInput(self["medianRadius"]) # Write out the result self["__ImageWriter"] = GafferImage.ImageWriter() self["__ImageWriter"]["in"].setInput(self["__Median"]["out"]) self["__ImageWriter"]["preTasks"][0].setInput( self["__ImageIntermediateWriter"]["task"]) # Convert result to texture self["__ConvertCommand"] = GafferDispatch.SystemCommand() # We shouldn't need a sub-shell and this prevents S.I.P on the Mac from # blocking the dylibs loaded by maketx. self["__ConvertCommand"]["shell"].setValue(False) self["__ConvertCommand"]["substitutions"].addChild( Gaffer.NameValuePlug("inFile", IECore.StringData(), "member1")) self["__ConvertCommand"]["substitutions"].addChild( Gaffer.NameValuePlug("outFile", IECore.StringData(), "member1")) self["__ConvertCommand"]["preTasks"][0].setInput( self["__ImageWriter"]["task"]) self["__ConvertCommand"]["command"].setValue( 'maketx --wrap clamp {inFile} -o {outFile}') self["__CommandSetupExpression"] = Gaffer.Expression() self["__CommandSetupExpression"].setExpression( inspect.cleandoc(""" outFileBase = context["wedge:outFile"] intermediateExr = outFileBase + ".intermediate.exr" parent["__ImageIntermediateWriter"]["fileName"] = intermediateExr parent["__ImageIntermediateReader"]["fileName"] = intermediateExr tmpExr = outFileBase + ".tmp.exr" parent["__ImageWriter"]["fileName"] = tmpExr parent["__ConvertCommand"]["substitutions"]["member1"]["value"] = tmpExr parent["__ConvertCommand"]["substitutions"]["member2"]["value"] = outFileBase + ".tx" """), "python") self["__ImageWedge"] = GafferDispatch.Wedge() self["__ImageWedge"]["preTasks"][0].setInput( self["__ConvertCommand"]["task"]) self["__ImageWedge"]["variable"].setValue('wedge:outFile') self["__ImageWedge"]["indexVariable"].setValue('wedge:outFileIndex') self["__ImageWedge"]["mode"].setValue(int( Gaffer.Wedge.Mode.StringList)) self["__CleanUpCommand"] = GafferDispatch.PythonCommand() self["__CleanUpCommand"]["preTasks"][0].setInput( self["__ImageWedge"]["task"]) self["__CleanUpCommand"]["variables"].addChild( Gaffer.NameValuePlug( "filesToDelete", Gaffer.StringVectorDataPlug( defaultValue=IECore.StringVectorData()), "member1")) self["__CleanUpCommand"]["command"].setValue( inspect.cleandoc(""" import os for tmpFile in variables["filesToDelete"]: os.remove( tmpFile ) """)) self["__CleanUpExpression"] = Gaffer.Expression() self["__CleanUpExpression"].setExpression( inspect.cleandoc(""" imageList = parent["__imageList"] toDelete = [] for outFileBase, inputExrs in imageList.items(): tmpExr = outFileBase + ".tmp.exr" intermediateExr = outFileBase + ".intermediate.exr" toDelete.extend( inputExrs ) toDelete.append( tmpExr ) toDelete.append( intermediateExr ) toDelete.append( parent["__indexFilePath"] ) parent["__CleanUpCommand"]["variables"]["member1"]["value"] = IECore.StringVectorData( toDelete ) """), "python") self["__CleanUpSwitch"] = GafferDispatch.TaskSwitch() self["__CleanUpSwitch"]["preTasks"][0].setInput( self["__ImageWedge"]["task"]) self["__CleanUpSwitch"]["preTasks"][1].setInput( self["__CleanUpCommand"]["task"]) self["__CleanUpSwitch"]["index"].setInput( self["cleanupIntermediateFiles"]) # Set up the list of input image files to process, and the corresponding list of # output files to wedge over self["__ImageSetupExpression"] = Gaffer.Expression() self["__ImageSetupExpression"].setExpression( inspect.cleandoc(""" f = open( parent["__indexFilePath"], "r" ) fileList = f.read().splitlines() fileDict = {} for i in fileList: rootName = i.rsplit( ".exr", 1 )[0] if rootName in fileDict: fileDict[ rootName ].append( i ) else: fileDict[ rootName ] = IECore.StringVectorData( [i] ) parent["__imageList"] = IECore.CompoundObject( fileDict ) parent["__ImageWedge"]["strings"] = IECore.StringVectorData( fileDict.keys() ) """), "python")
def testPlane( self ) : mesh = IECoreScene.MeshPrimitive.createPlane( imath.Box2f( imath.V2f( -1 ), imath.V2f( 1 ) ), imath.V2i( 10 ) ) IECoreScene.TriangulateOp()( input = mesh, copyInput = False ) meshReversed = mesh.copy() IECoreScene.MeshAlgo.reverseWinding( meshReversed ) evaluator = IECoreScene.MeshPrimitiveEvaluator( mesh ) evaluatorReversed = IECoreScene.MeshPrimitiveEvaluator( meshReversed ) result = evaluator.createResult() resultReversed = evaluatorReversed.createResult() for i in range( 0, 1000 ) : p = imath.V3f( random.uniform( -1.0, 1.0 ), random.uniform( -1.0, 1.0 ), 0 ) evaluator.closestPoint( p, result ) evaluatorReversed.closestPoint( p, resultReversed ) self.assertEqual( resultReversed.normal(), -result.normal() ) reversedUV = resultReversed.vec2PrimVar( meshReversed["uv"] ) uv = result.vec2PrimVar( mesh["uv"] ) self.assertAlmostEqual( reversedUV[0], uv[0], delta = 0.0001 ) self.assertAlmostEqual( reversedUV[1], uv[1], delta = 0.0001 )
def testTileOrigin(self): ts = GafferImage.ImagePlug.tileSize() testCases = [(imath.V2i(ts - 1, ts - 1), imath.V2i(0, 0)), (imath.V2i(ts, ts - 1), imath.V2i(ts, 0)), (imath.V2i(ts, ts), imath.V2i(ts, ts)), (imath.V2i(ts * 3 - 1, ts + 5), imath.V2i(ts * 2, ts)), (imath.V2i(ts * 3, ts - 5), imath.V2i(ts * 3, 0)), (imath.V2i(-ts + ts / 2, 0), imath.V2i(-ts, 0)), (imath.V2i(ts * 5 + ts / 3, -ts * 4), imath.V2i(ts * 5, -ts * 4)), (imath.V2i(-ts + 1, -ts - 1), imath.V2i(-ts, -ts * 2))] for input, expectedResult in testCases: self.assertEqual(GafferImage.ImagePlug.tileOrigin(input), expectedResult)
def __init__(self, plug, **kw): l = GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Horizontal, spacing=4) GafferUI.PlugValueWidget.__init__(self, l, plug, **kw) mode = plug["mode"].getValue() with l: self.__indexLabel = GafferUI.Label() labelFont = QtGui.QFont(self.__indexLabel._qtWidget().font()) labelFont.setBold(True) labelFont.setPixelSize(10) labelFontMetrics = QtGui.QFontMetrics(labelFont) self.__indexLabel._qtWidget().setMinimumWidth( labelFontMetrics.width("99")) self.__modeImage = GafferUI.Image("sourceCursor.png") self.__positionLabel = GafferUI.Label() self.__positionLabel._qtWidget().setMinimumWidth( labelFontMetrics.width("9999 9999 -> 9999 9999")) self.__swatch = GafferUI.ColorSwatch() self.__swatch._qtWidget().setFixedWidth(12) self.__swatch._qtWidget().setFixedHeight(12) self.__busyWidget = GafferUI.BusyWidget(size=12) self.__rgbLabel = GafferUI.Label() self.__rgbLabel._qtWidget().setMinimumWidth( labelFontMetrics.width("RGBA : 99999 99999 99999 99999")) self.__hsvLabel = GafferUI.Label() self.__hsvLabel._qtWidget().setMinimumWidth( labelFontMetrics.width("HSV : 99999 99999 99999")) self.__exposureLabel = GafferUI.Label() self.__exposureLabel._qtWidget().setMinimumWidth( labelFontMetrics.width("EV : 19.9")) l.addChild(GafferUI.Spacer(size=imath.V2i(0))) if mode == GafferImageUI.ImageView.ColorInspectorPlug.Mode.Cursor: m = IECore.MenuDefinition() m.append( "/Pixel Inspector", { "command": functools.partial( Gaffer.WeakMethod(self.__addClick), GafferImageUI. ImageView.ColorInspectorPlug.Mode.Pixel) }) m.append( "/Area Inspector", { "command": functools.partial( Gaffer.WeakMethod(self.__addClick), GafferImageUI. ImageView.ColorInspectorPlug.Mode.Area) }) button = GafferUI.MenuButton("", "plus.png", hasFrame=False, menu=GafferUI.Menu( m, title="Add Color Inspector")) else: button = GafferUI.Button("", "delete.png", hasFrame=False) button.clickedSignal().connect(Gaffer.WeakMethod( self.__deleteClick), scoped=False) self.__pixel = imath.V2i(0) self.__createInspectorStartPosition = None if plug.getName() == "ColorInspectorPlug": viewportGadget = plug.node().viewportGadget() imageGadget = viewportGadget.getPrimaryChild() imageGadget.mouseMoveSignal().connect(Gaffer.WeakMethod( self.__mouseMove), scoped=False) imageGadget.buttonPressSignal().connect(Gaffer.WeakMethod( self.__buttonPress), scoped=False) imageGadget.buttonReleaseSignal().connect(Gaffer.WeakMethod( self.__buttonRelease), scoped=False) imageGadget.dragBeginSignal().connect(Gaffer.WeakMethod( self.__dragBegin), scoped=False) imageGadget.dragEnterSignal().connect(Gaffer.WeakMethod( self.__dragEnter), scoped=False) imageGadget.dragMoveSignal().connect(Gaffer.WeakMethod( self.__dragMove), scoped=False) imageGadget.dragEndSignal().connect(Gaffer.WeakMethod( self.__dragEnd), scoped=False) self.__swatch.buttonPressSignal().connect(Gaffer.WeakMethod( self.__buttonPress), scoped=False) self.__swatch.dragBeginSignal().connect(Gaffer.WeakMethod( self.__dragBegin), scoped=False) self.__swatch.dragEndSignal().connect(Gaffer.WeakMethod( self.__dragEnd), scoped=False) plug.node()["colorInspector"]["evaluator"]["pixelColor"].getInput( ).node().plugDirtiedSignal().connect(Gaffer.WeakMethod( self.__updateFromImageNode), scoped=False) plug.node().plugDirtiedSignal().connect(Gaffer.WeakMethod( self._plugDirtied), scoped=False) plug.node()["in"].getInput().node().scriptNode().context( ).changedSignal().connect(Gaffer.WeakMethod(self.__updateFromContext), scoped=False) Gaffer.Metadata.plugValueChangedSignal(self.getPlug().node()).connect( Gaffer.WeakMethod(self.__plugMetadataChanged), scoped=False) self.__updateLabels(imath.V2i(0), imath.Color4f(0, 0, 0, 1)) # Set initial state of mode icon self._plugDirtied(plug["mode"])
def testRoundTrip( self ) : mesh = IECoreScene.MeshPrimitive.createPlane( imath.Box2f( imath.V2f( -1 ), imath.V2f( 1 ) ), imath.V2i( 10 ) ) meshReversed = mesh.copy() IECoreScene.MeshAlgo.reverseWinding( meshReversed ) meshReversedAgain = meshReversed.copy() IECoreScene.MeshAlgo.reverseWinding( meshReversedAgain ) self.assertEqual( mesh, meshReversedAgain )
def testBasics( self ): representativeImage = GafferImage.ImageReader() representativeImage["fileName"].setValue( self.representativeImagePath ) flatImage = GafferImage.ImageReader() flatImage["fileName"].setValue( self.flatImagePath ) rc = GafferImage.DeepRecolor() rc["in"].setInput( representativeImage["out"] ) rc["colorSource"].setInput( flatImage["out"] ) representativeSampleCounts = GafferImage.DeepSampleCounts() representativeSampleCounts["in"].setInput( representativeImage["out"] ) rcSampleCounts = GafferImage.DeepSampleCounts() rcSampleCounts["in"].setInput( rc["out"] ) # Make sure we keep all the deep samples self.assertImagesEqual( representativeSampleCounts["out"], rcSampleCounts["out"] ) rcFlat = GafferImage.DeepToFlat() rcFlat["in"].setInput( rc["out"] ) representativeFlat = GafferImage.DeepToFlat() representativeFlat["in"].setInput( representativeImage["out"] ) unpremult = GafferImage.Unpremultiply() unpremult["in"].setInput( flatImage["out"] ) flatCombine = GafferImage.CopyChannels() flatCombine["in"][0].setInput( representativeFlat["out"] ) flatCombine["in"][1].setInput( unpremult["out"] ) flatCombine["channels"].setValue( "[RGB]" ) premult = GafferImage.Premultiply() premult["in"].setInput( flatCombine["out"] ) # Make sure that the default recolor matches the flat value of premulting by the deep alpha self.assertImagesEqual( rcFlat["out"], premult["out"], maxDifference = 1e-6 ) compare = GafferImage.Merge() compare["in"][0].setInput( rcFlat["out"] ) compare["in"][1].setInput( premult["out"] ) compare["operation"].setValue( GafferImage.Merge.Operation.Difference ) compareStats = GafferImage.ImageStats() compareStats["in"].setInput( compare["out"] ) compareStats["area"].setValue( imath.Box2i( imath.V2i( 0, 0 ), imath.V2i( 150, 100 ) ) ) m = compareStats["max"].getValue() a = compareStats["average"].getValue() for i in range( 4 ): self.assertLessEqual( m[i], 1e-6 ) self.assertLessEqual( a[i], 1e-8 ) rc["useColorSourceAlpha"].setValue( True ) m = compareStats["max"].getValue() a = compareStats["average"].getValue() for i in range( 3 ): self.assertGreater( m[i], 0.4 ) self.assertGreater( a[i], 0.0001 ) # Make sure that using useColorSourceAlpha basically matches the original color source after # flattening. ( It's not exact because of a few pixels with zero samples in the deep which # we can't do anything with ) compare["in"][1].setInput( flatImage["out"] ) m = compareStats["max"].getValue() a = compareStats["average"].getValue() for i in range( 4 ): self.assertLessEqual( m[i], 0.5 ) self.assertLessEqual( a[i], 0.0003 )
def testEmpty(self): self.assertTrue(GafferImage.BufferAlgo.empty(imath.Box2i())) self.assertTrue( GafferImage.BufferAlgo.empty( imath.Box2i(imath.V2i(0), imath.V2i(0)))) self.assertFalse( GafferImage.BufferAlgo.empty( imath.Box2i(imath.V2i(0), imath.V2i(1)))) self.assertTrue( GafferImage.BufferAlgo.empty( imath.Box2i(imath.V2i(2147483646), imath.V2i(-2147483646)))) self.assertTrue( GafferImage.BufferAlgo.empty( imath.Box2i(imath.V2i(0), imath.V2i(-2147483647)))) self.assertTrue( GafferImage.BufferAlgo.empty( imath.Box2i(imath.V2i(2147483647), imath.V2i(0)))) self.assertTrue( GafferImage.BufferAlgo.empty( imath.Box2i(imath.V2i(-1), imath.V2i(-2147483647)))) self.assertTrue( GafferImage.BufferAlgo.empty( imath.Box2i(imath.V2i(2147483647), imath.V2i(1)))) self.assertTrue( GafferImage.BufferAlgo.empty( imath.Box2i(imath.V2i(1), imath.V2i(-2147483647)))) self.assertTrue( GafferImage.BufferAlgo.empty( imath.Box2i(imath.V2i(2147483647), imath.V2i(-1))))
def testClamp(self): self.assertEqual( GafferImage.BufferAlgo.clamp( imath.V2i(5, 6), imath.Box2i(imath.V2i(0), imath.V2i(10))), imath.V2i(5, 6)) self.assertEqual( GafferImage.BufferAlgo.clamp( imath.V2i(10, 6), imath.Box2i(imath.V2i(0), imath.V2i(10))), imath.V2i(9, 6)) self.assertEqual( GafferImage.BufferAlgo.clamp( imath.V2i(0, 6), imath.Box2i(imath.V2i(0), imath.V2i(10))), imath.V2i(0, 6)) self.assertEqual( GafferImage.BufferAlgo.clamp( imath.V2i(5, -1), imath.Box2i(imath.V2i(0), imath.V2i(10))), imath.V2i(5, 0)) self.assertEqual( GafferImage.BufferAlgo.clamp( imath.V2i(5, 10), imath.Box2i(imath.V2i(0), imath.V2i(10))), imath.V2i(5, 9))
def testDynamicPlugsAndGIL(self): script = Gaffer.ScriptNode() script["plane"] = GafferScene.Plane() script["plane"]["divisions"].setValue(imath.V2i(20)) script["sphere"] = GafferScene.Sphere() script["expression"] = Gaffer.Expression() script["expression"].setExpression( "parent['sphere']['radius'] = context.getFrame()") script["instancer"] = GafferScene.Instancer() script["instancer"]["in"].setInput(script["plane"]["out"]) script["instancer"]["instances"].setInput(script["sphere"]["out"]) script["instancer"]["parent"].setValue("/plane") script["attributes"] = GafferScene.CustomAttributes() script["attributes"]["in"].setInput(script["instancer"]["out"]) script["outputs"] = GafferScene.Outputs() script["outputs"]["in"].setInput(script["attributes"]["out"]) # Simulate an InteractiveRender or Viewer traversal of the scene # every time it is dirtied. If the GIL isn't released when dirtiness # is signalled, we'll end up with a deadlock as the traversal enters # python on another thread to evaluate the expression. We increment the frame # between each test to ensure the expression result is not cached and # we do truly enter python. traverseConnection = Gaffer.ScopedConnection( GafferSceneTest.connectTraverseSceneToPlugDirtiedSignal( script["outputs"]["out"])) with Gaffer.Context() as c: c.setFrame(1) script["attributes"]["attributes"].addMember( "test1", IECore.IntData(10)) c.setFrame(2) script["attributes"]["attributes"].addOptionalMember( "test2", IECore.IntData(20)) c.setFrame(3) script["attributes"]["attributes"].addMembers( IECore.CompoundData({ "test3": 30, "test4": 40, })) c.setFrame(4) p = script["attributes"]["attributes"][0] del script["attributes"]["attributes"][p.getName()] c.setFrame(5) script["attributes"]["attributes"].addChild(p) c.setFrame(6) script["attributes"]["attributes"].removeChild(p) c.setFrame(7) script["attributes"]["attributes"].setChild(p.getName(), p) c.setFrame(8) script["attributes"]["attributes"].removeChild(p) c.setFrame(9) script["attributes"]["attributes"][p.getName()] = p c.setFrame(10) script["outputs"].addOutput( "test", IECoreScene.Output("beauty.exr", "exr", "rgba"))
def runInteractive(self, useUI, useBlur, resolution): script = Gaffer.ScriptNode() script["Camera"] = GafferScene.Camera() script["Camera"]["transform"]["translate"]["z"].setValue(6) script["Sphere"] = GafferScene.Sphere("Sphere") script["Sphere"]["radius"].setValue(10) script["ImageShader"] = GafferArnold.ArnoldShader() script["ImageShader"].loadShader("image") script["ImageShader"]["parameters"]["filename"].setValue( os.path.dirname(__file__) + "/../GafferImageTest/images/GafferChecker.exr") script["ImageShader"]["parameters"]["sscale"].setValue(16) script["ImageShader"]["parameters"]["tscale"].setValue(16) script["ShaderAssignment"] = GafferScene.ShaderAssignment() script["ShaderAssignment"]["in"].setInput(script["Sphere"]["out"]) script["ShaderAssignment"]["shader"].setInput( script["ImageShader"]["out"]) script["Group"] = GafferScene.Group() script["Group"]["in"][0].setInput(script["Camera"]["out"]) script["Group"]["in"][1].setInput(script["ShaderAssignment"]["out"]) script["StandardOptions"] = GafferScene.StandardOptions() script["StandardOptions"]["in"].setInput(script["Group"]["out"]) script["StandardOptions"]["options"]["renderCamera"]["value"].setValue( '/group/camera') script["StandardOptions"]["options"]["renderCamera"][ "enabled"].setValue(True) script["StandardOptions"]["options"]["renderResolution"][ "value"].setValue(imath.V2i(resolution, resolution)) script["StandardOptions"]["options"]["renderResolution"][ "enabled"].setValue(True) script["ArnoldOptions"] = GafferArnold.ArnoldOptions("ArnoldOptions") script["ArnoldOptions"]["in"].setInput( script["StandardOptions"]["out"]) # Make sure we leave some CPU available for Gaffer script["ArnoldOptions"]["options"]["threads"]["value"].setValue(-1) script["ArnoldOptions"]["options"]["threads"]["enabled"].setValue(True) script["Outputs"] = GafferScene.Outputs() script["Outputs"].addOutput( "beauty", IECoreScene.Output( "Interactive/Beauty", "ieDisplay", "rgba", { "quantize": IECore.IntVectorData([0, 0, 0, 0]), "driverType": 'ClientDisplayDriver', "displayHost": 'localhost', "displayPort": str(GafferImage.Catalogue.displayDriverServer().portNumber( )), "remoteDisplayType": 'GafferImage::GafferDisplayDriver', "filter": 'box', })) script["Outputs"]["in"].setInput(script["ArnoldOptions"]["out"]) script[ "InteractiveArnoldRender"] = GafferArnold.InteractiveArnoldRender( ) script["InteractiveArnoldRender"]["in"].setInput( script["Outputs"]["out"]) script["Catalogue"] = GafferImage.Catalogue("Catalogue") script["Catalogue"]["directory"].setValue(self.temporaryDirectory() + "/catalogues/test") script["Blur"] = GafferImage.Blur("Blur") script["Blur"]["in"].setInput(script["Catalogue"]["out"]) script["Blur"]["radius"]["x"].setValue(1.0) script["Blur"]["radius"]["y"].setValue(1.0) watchNode = script["Blur"] if useBlur else script["Catalogue"] if useUI: with GafferUI.Window() as window: window.setFullScreen(True) viewer = GafferUI.Viewer(script) window.setVisible(True) viewer.setNodeSet(Gaffer.StandardSet([watchNode])) script['InteractiveArnoldRender']['state'].setValue( GafferScene.InteractiveRender.State.Running) self.waitForIdle(10) viewer.view().viewportGadget().frame( viewer.view().viewportGadget().getPrimaryChild().bound(), imath.V3f(0, 0, 1)) frameCounter = {'i': 0} def testFunc(): frameCounter['i'] += 1 script["Camera"]["transform"]["translate"]["x"].setValue( math.sin(frameCounter['i'] * 0.1)) if frameCounter['i'] >= 50: GafferUI.EventLoop.mainEventLoop().stop() timer = QtCore.QTimer() timer.setInterval(20) timer.timeout.connect(testFunc) GafferImageUI.ImageGadget.resetTileUpdateCount() timer.start() with GafferTest.TestRunner.PerformanceScope() as ps: GafferUI.EventLoop.mainEventLoop().start() ps.setNumIterations( GafferImageUI.ImageGadget.tileUpdateCount()) script['InteractiveArnoldRender']['state'].setValue( GafferScene.InteractiveRender.State.Stopped) del window, viewer, timer self.waitForIdle(10) else: with GafferTest.ParallelAlgoTest.UIThreadCallHandler() as h: with IECore.CapturingMessageHandler() as mh: script['InteractiveArnoldRender']['state'].setValue( GafferScene.InteractiveRender.State.Running) h.waitFor(2) arnoldStartupErrors = mh.messages tc = Gaffer.ScopedConnection( GafferImageTest.connectProcessTilesToPlugDirtiedSignal( watchNode["out"])) with GafferTest.TestRunner.PerformanceScope() as ps: with Gaffer.PerformanceMonitor() as m: for i in range(250): script["Camera"]["transform"]["translate"][ "x"].setValue(math.sin((i + 1) * 0.1)) h.waitFor(0.02) ps.setNumIterations( m.plugStatistics( watchNode["out"] ["channelData"].source()).computeCount) script['InteractiveArnoldRender']['state'].setValue( GafferScene.InteractiveRender.State.Stopped)
def testContextChangedAndGIL(self): script = Gaffer.ScriptNode() script["plane"] = GafferScene.Plane() script["plane"]["divisions"].setValue(imath.V2i(20)) script["sphere"] = GafferScene.Sphere() script["expression"] = Gaffer.Expression() script["expression"].setExpression( "parent['sphere']['radius'] = context.get( 'minRadius', 0.1 ) + context.getFrame()" ) script["instancer"] = GafferScene.Instancer() script["instancer"]["in"].setInput(script["plane"]["out"]) script["instancer"]["instances"].setInput(script["sphere"]["out"]) script["instancer"]["parent"].setValue("/plane") context = Gaffer.Context() traverseConnection = Gaffer.ScopedConnection( GafferSceneTest.connectTraverseSceneToContextChangedSignal( script["instancer"]["out"], context)) with context: context.setFrame(10) context.setFramesPerSecond(50) context.setTime(1) context.set("a", 1) context.set("a", 2.0) context.set("a", "a") context.set("a", imath.V2i()) context.set("a", imath.V3i()) context.set("a", imath.V2f()) context.set("a", imath.V3f()) context.set("a", imath.Color3f()) context.set("a", IECore.BoolData(True)) context["b"] = 1 context["b"] = 2.0 context["b"] = "b" context["b"] = imath.V2i() context["b"] = imath.V3i() context["b"] = imath.V2f() context["b"] = imath.V3f() context["b"] = imath.Color3f() context["b"] = IECore.BoolData(True) with Gaffer.BlockedConnection(traverseConnection): # Must add it with the connection disabled, otherwise # the addition causes a traversal, and then remove() gets # all its results from the cache. context["minRadius"] = 0.2 context.remove("minRadius") with Gaffer.BlockedConnection(traverseConnection): context["minRadius"] = 0.3 del context["minRadius"]
def testIndexPrimitiveVariables(self): # +-----------------+ # | |XXXXX| | invert = True (3 faces remain) # +------------------> | |XXXXX| | # | | |XXXXX| | # | +-----------------+ # + | |XXXXX| | # 12 13 14 15 | |XXXXX| | # +-----+-----+-----+ | |XXXXX| | # | | | | +-----------------+ # | | | | | |XXXXX| | # |8 |9 |10 |11 | |XXXXX| | # +-----------------+ | |XXXXX| | # | | | | +-----------------+ # | | | | # |4 |5 |6 |7 +-----------------+ # +-----------------+ |XXXXX| |XXXXX| invert = False (6 faces remain) # | | | | |XXXXX| |XXXXX| # | | | | |XXXXX| |XXXXX| # |0 |1 |2 |3 +-----------------+ # +-----+-----+-----+ |XXXXX| |XXXXX| # |XXXXX| |XXXXX| # + |XXXXX| |XXXXX| # | +-----------------+ # +------------------> |XXXXX| |XXXXX| # |XXXXX| |XXXXX| # |XXXXX| |XXXXX| # +-----------------+ planeMesh3x3 = IECoreScene.MeshPrimitive.createPlane( imath.Box2f(imath.V2f(0), imath.V2f(2)), imath.V2i(3, 3)) primvarUniformNonIndexed = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Uniform, IECore.IntVectorData([0, 1, 0, 0, 1, 0, 0, 1, 0])) primvarUniformIndexed = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Uniform, IECore.IntVectorData([0, 1, 0]), IECore.IntVectorData([0, 1, 2, 0, 1, 2, 0, 1, 2])) primvarVertexNonIndexed = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Vertex, IECore.IntVectorData( [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3])) primvarVertexIndexed = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Vertex, IECore.IntVectorData([4, 3, 2, 1]), IECore.IntVectorData( [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3])) primvarFaceVaryingIndexed = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.FaceVarying, IECore.IntVectorData([3, 2, 1]), IECore.IntVectorData([ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2 ])) planeMesh3x3["primvarUniformNonIndexed"] = primvarUniformNonIndexed planeMesh3x3["primvarUniformIndexed"] = primvarUniformIndexed planeMesh3x3["primvarVertexNonIndexed"] = primvarVertexNonIndexed planeMesh3x3["primvarVertexIndexed"] = primvarVertexIndexed planeMesh3x3["primvarFaceVaryingIndexed"] = primvarFaceVaryingIndexed self.assertTrue(planeMesh3x3.arePrimitiveVariablesValid()) # delete an indexed uniform primitive variable using a non indexed uniform primitive variable to flag which faces to delete facesDeletedMesh = IECoreScene.MeshAlgo.deleteFaces( planeMesh3x3, planeMesh3x3["primvarUniformNonIndexed"], invert=False) self.assertTrue(facesDeletedMesh.arePrimitiveVariablesValid()) self.assertEqual(facesDeletedMesh.numFaces(), 6) self.assertEqual(facesDeletedMesh["primvarUniformIndexed"].data, IECore.IntVectorData([0, 0])) self.assertEqual(facesDeletedMesh["primvarUniformIndexed"].indices, IECore.IntVectorData([0, 1, 0, 1, 0, 1])) # delete an indexed vertex primitive variable using an indexed uniform primitive variable to flag which faces to delete facesDeletedMesh = IECoreScene.MeshAlgo.deleteFaces( planeMesh3x3, planeMesh3x3["primvarUniformNonIndexed"], invert=True) self.assertTrue(facesDeletedMesh.arePrimitiveVariablesValid()) self.assertEqual(facesDeletedMesh.numFaces(), 3) self.assertEqual(facesDeletedMesh["primvarVertexIndexed"].data, IECore.IntVectorData([4, 3, 2, 1])) self.assertEqual(facesDeletedMesh["primvarVertexIndexed"].indices, IECore.IntVectorData([0, 0, 1, 1, 2, 2, 3, 3])) # delete an indexed uniform primitive variable using an indexed uniform primitive variable to flag which faces to delete facesDeletedMesh = IECoreScene.MeshAlgo.deleteFaces( planeMesh3x3, planeMesh3x3["primvarUniformIndexed"], invert=False) self.assertTrue(facesDeletedMesh.arePrimitiveVariablesValid()) self.assertEqual(facesDeletedMesh.numFaces(), 6) self.assertEqual(facesDeletedMesh["primvarUniformIndexed"].data, IECore.IntVectorData([0, 0])) self.assertEqual(facesDeletedMesh["primvarUniformIndexed"].indices, IECore.IntVectorData([0, 1, 0, 1, 0, 1])) # delete an indexed FaceVarying primitive variable using an indexed uniform primitive variable to flag which faces to delete facesDeletedMesh = IECoreScene.MeshAlgo.deleteFaces( planeMesh3x3, planeMesh3x3["primvarUniformIndexed"], invert=True) self.assertTrue(facesDeletedMesh.arePrimitiveVariablesValid()) self.assertEqual(facesDeletedMesh.numFaces(), 3) self.assertEqual(facesDeletedMesh["primvarFaceVaryingIndexed"].data, IECore.IntVectorData([2])) self.assertEqual( facesDeletedMesh["primvarFaceVaryingIndexed"].indices, IECore.IntVectorData([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]))
def testUniformIndices( self ) : m = IECoreScene.MeshPrimitive.createPlane( imath.Box2f( imath.V2f( -4 ), imath.V2f( 4 ) ), divisions = imath.V2i( 2, 2 ) ) m["myString"] = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Uniform, IECore.StringVectorData( [ "a", "b" ] ), IECore.IntVectorData( [ 1, 0, 0, 1 ] ) ) m2 = IECoreScene.MeshAlgo.triangulate( m ) self.assertTrue( m2.arePrimitiveVariablesValid() ) self.assertEqual( m2["myString"].data, m["myString"].data ) self.assertEqual( m2["myString"].indices, IECore.IntVectorData( [ 1, 1, 0, 0, 0, 0, 1, 1 ] ) )
def __init__( self, opInstanceOrOpHolderInstance, title=None, sizeMode=GafferUI.Window.SizeMode.Manual, postExecuteBehaviour = PostExecuteBehaviour.FromUserData, executeInBackground = False, defaultButton = DefaultButton.FromUserData, executeImmediately = False, **kw ) : # sort out our op and op holder if isinstance( opInstanceOrOpHolderInstance, IECore.Op ) : opInstance = opInstanceOrOpHolderInstance self.__node = GafferCortex.ParameterisedHolderNode() self.__node.setParameterised( opInstance ) # set the current plug values as userDefaults to provide # a clean NodeUI based on the initial settings of the Op. # we assume that if an OpHolder was passed directly then # the metadata has already been setup as preferred. self.__setUserDefaults( self.__node ) else : self.__node = opInstanceOrOpHolderInstance opInstance = self.__node.getParameterised()[0] # initialise the dialogue if title is None : title = IECore.CamelCase.toSpaced( opInstance.typeName() ) GafferUI.Dialogue.__init__( self, title, sizeMode=sizeMode, **kw ) # decide what we'll do after execution. if postExecuteBehaviour == self.PostExecuteBehaviour.FromUserData : postExecuteBehaviour = self.PostExecuteBehaviour.DisplayResult d = None with IECore.IgnoredExceptions( KeyError ) : d = opInstance.userData()["UI"]["postExecuteBehaviour"] if d is not None : for v in self.PostExecuteBehaviour.values() : if str( v ).lower() == d.value.lower() : postExecuteBehaviour = v break else : # backwards compatibility with batata with IECore.IgnoredExceptions( KeyError ) : d = opInstance.userData()["UI"]["closeAfterExecution"] if d is not None : postExecuteBehaviour = self.PostExecuteBehaviour.Close if d.value else self.PostExecuteBehaviour.DisplayResult self.__postExecuteBehaviour = postExecuteBehaviour self.__executeInBackground = executeInBackground self.__defaultButton = defaultButton # make a frame to contain our main ui element. this will # contain different elements depending on our state. self.__frame = GafferUI.Frame() self._setWidget( self.__frame ) # get the ui for the op - we'll use this when we want # the user to edit parameters. self.__parameterEditingUI = GafferUI.NodeUI.create( self.__node ) # build a ui element for progress feedback and suchlike. # we'll use this when executing and displaying the result. with GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Vertical, spacing = 4 ) as self.__progressUI : GafferUI.Spacer( imath.V2i( 1 ), preferredSize = imath.V2i( 1, 1 ) ) self.__progressIconFrame = GafferUI.Frame( borderStyle = GafferUI.Frame.BorderStyle.None_, parenting = { "horizontalAlignment" : GafferUI.HorizontalAlignment.Center } ) self.__progressLabel = GafferUI.Label( parenting = { "expand" : True, "horizontalAlignment" : GafferUI.HorizontalAlignment.Center, } ) GafferUI.Spacer( imath.V2i( 250, 1 ), preferredSize = imath.V2i( 250, 1 ) ) with GafferUI.Collapsible( "Details", collapsed = True ) as self.__messageCollapsible : self.__messageWidget = GafferUI.MessageWidget( toolbars = True ) # connect to the collapsible state change so we can increase the window # size when the details pane is first shown. self.__messageCollapsibleStateChangedConnection = self.__messageCollapsible.stateChangedSignal().connect( Gaffer.WeakMethod( self.__messageCollapsibleStateChanged ) ) # add buttons. our buttons mean different things depending on our current state, # but they equate roughly to going forwards or going backwards. self.__backButton = self._addButton( "Back" ) self.__forwardButton = self._addButton( "Forward" ) self.__preExecuteSignal = GafferUI.WidgetSignal() self.__postExecuteSignal = Gaffer.Signal2() self.__opExecutedSignal = Gaffer.Signal1() self.__haveResizedToFitParameters = False if executeImmediately : self.__initiateExecution() else : self.__initiateParameterEditing()
def __init__(self, name="__CameraSetup"): GafferScene.FilteredSceneProcessor.__init__(self, name) # Public plugs self["cameraGroup"] = Gaffer.StringPlug("cameraGroup", Gaffer.Plug.Direction.In, "__TEXTUREBAKE_CAMERAS") self["bakeDirectory"] = Gaffer.StringPlug("bakeDirectory", Gaffer.Plug.Direction.In, "") self["defaultFileName"] = Gaffer.StringPlug( "defaultFileName", Gaffer.Plug.Direction.In, "${bakeDirectory}/<AOV>/<AOV>.<UDIM>.exr") self["defaultResolution"] = Gaffer.IntPlug( "defaultResolution", Gaffer.Plug.Direction.In, 512) self["uvSet"] = Gaffer.StringPlug("uvSet", Gaffer.Plug.Direction.In, "uv") self["normalOffset"] = Gaffer.FloatPlug("normalOffset", Gaffer.Plug.Direction.In, 0.1) self["aovs"] = Gaffer.StringPlug("aovs", Gaffer.Plug.Direction.In, "beauty:rgba") self["tasks"] = Gaffer.IntPlug("tasks", Gaffer.Plug.Direction.In, 1) self["taskIndex"] = Gaffer.IntPlug("taskIndex", Gaffer.Plug.Direction.In, 0) # Output self["renderFileList"] = Gaffer.StringVectorDataPlug( "renderFileList", Gaffer.Plug.Direction.Out, defaultValue=IECore.StringVectorData()) self["renderFileList"].setFlags(Gaffer.Plug.Flags.Serialisable, False) # Private internal network self["__udimQuery"] = GafferScene.UDIMQuery() self["__udimQuery"]["in"].setInput(self["in"]) self["__udimQuery"]["uvSet"].setInput(self["uvSet"]) self["__udimQuery"]["attributes"].setValue( "bake:resolution bake:fileName") self["__udimQuery"]["filter"].setInput(self["filter"]) self["__chunkedBakeInfo"] = Gaffer.CompoundObjectPlug( "__chunkedBakeInfo", Gaffer.Plug.Direction.In, IECore.CompoundObject()) self["__chunkedBakeInfo"].setFlags(Gaffer.Plug.Flags.Serialisable, False) self["__chunkExpression"] = Gaffer.Expression() self["__chunkExpression"].setExpression( inspect.cleandoc(""" # Locate the next point in the list of files to bake where we can split the list into chunks without # seperating two files that need to get combined into the same texture def nextChunkBreak( i, l ): while i > 0 and i < len( l ) and ( l[i - 1].get("udim") == l[i].get("udim") and l[i - 1].get("fileName") == l[i].get("fileName") ): i += 1 return i rawInfo = parent["__udimQuery"]["out"] defaultFileName = parent["defaultFileName"] defaultResolution = parent["defaultResolution"] listInfo = [] for udim, meshes in rawInfo.items(): for mesh, extraAttributes in meshes.items(): resolution = defaultResolution if "bake:resolution" in extraAttributes: resolution = extraAttributes["bake:resolution"].value fileName = defaultFileName if "bake:fileName" in extraAttributes: fileName = extraAttributes["bake:fileName"].value listInfo.append( { "udim" : int( udim ), "mesh" : mesh, "resolution" : resolution, "fileName" : fileName } ) listInfo.sort( key = lambda i: (i["fileName"], i["udim"] ) ) info = IECore.CompoundObject() numTasks = parent["tasks"] taskIndex = parent["taskIndex"] chunkStart = nextChunkBreak( ( taskIndex * len( listInfo ) ) / numTasks, listInfo ) chunkEnd = nextChunkBreak( ( ( taskIndex + 1 ) * len( listInfo ) ) / numTasks, listInfo ) dupeCount = 0 prevFileName = "" for i in listInfo[chunkStart:chunkEnd]: o = IECore.CompoundObject() o["mesh"] = IECore.StringData( i["mesh"] ) o["udim"] = IECore.IntData( i["udim"] ) o["resolution"] = IECore.IntData( i["resolution"] ) udimStr = str( i["udim"] ) fileName = i["fileName"].replace( "<UDIM>", udimStr ) if fileName == prevFileName: dupeCount += 1 fileName = fileName + ".layer" + str( dupeCount ) else: prevFileName = fileName dupeCount = 0 o["fileName"] = IECore.StringData( fileName ) name = o["mesh"].value.replace( "/", "_" ) + "." + udimStr info[ name ] = o parent["__chunkedBakeInfo"] = info fileList = [] for name, i in info.items(): fileName = i["fileName"].value for nameAndAov in parent["aovs"].strip( " " ).split( " " ): fileList.append( i["fileName"].value.replace( "<AOV>", nameAndAov.split(":")[0] ) ) parent["renderFileList"] = IECore.StringVectorData( fileList ) """), "python") self["__parent"] = GafferScene.Parent() self["__parent"]["parent"].setValue("/") for c in [ 'bound', 'transform', 'attributes', 'object', 'childNames', 'setNames', 'set' ]: self["__parent"]["in"][c].setInput(self["in"][c]) self["__outputExpression"] = Gaffer.Expression() self["__outputExpression"].setExpression( inspect.cleandoc(""" import IECoreScene # Transfer all input globals except for outputs inGlobals = parent["in"]["globals"] outGlobals = IECore.CompoundObject() for key, value in inGlobals.items(): if not key.startswith( "output:" ): outGlobals[key] = value # Make our own outputs info = parent["__chunkedBakeInfo"] for cameraName, i in info.items(): params = IECore.CompoundData() fileName = i["fileName"].value params["camera"] = IECore.StringData( "/" + parent["cameraGroup"] + "/" + cameraName ) for nameAndAov in parent["aovs"].strip( " " ).split( " " ): tokens = nameAndAov.split( ":" ) if len( tokens ) != 2: raise RuntimeError( "Invalid bake aov specification: %s It should contain a : between name and data." ) ( aovName, aov ) = tokens aovFileName = fileName.replace( "<AOV>", aovName ) outGlobals["output:" + cameraName + "." + aov] = IECoreScene.Output( aovFileName, "exr", aov + " RGBA", params ) parent["__parent"]["in"]["globals"] = outGlobals """), "python") self["__camera"] = GafferScene.Camera() self["__camera"]["projection"].setValue("orthographic") self["__cameraTweaks"] = GafferScene.CameraTweaks() self["__cameraTweaks"]["in"].setInput(self["__camera"]["out"]) self["__cameraTweaks"]["tweaks"][ "projection"] = GafferScene.TweakPlug("projection", "uv_camera") self["__cameraTweaks"]["tweaks"][ "resolution"] = GafferScene.TweakPlug("resolution", imath.V2i(0)) self["__cameraTweaks"]["tweaks"][ "u_offset"] = GafferScene.TweakPlug("u_offset", 0.0) self["__cameraTweaks"]["tweaks"][ "v_offset"] = GafferScene.TweakPlug("v_offset", 0.0) self["__cameraTweaks"]["tweaks"]["mesh"] = GafferScene.TweakPlug( "mesh", "") self["__cameraTweaks"]["tweaks"]["uv_set"] = GafferScene.TweakPlug( "uv_set", "") self["__cameraTweaks"]["tweaks"][ "extend_edges"] = GafferScene.TweakPlug("extend_edges", False) self["__cameraTweaks"]["tweaks"]["offset"] = GafferScene.TweakPlug( "offset", 0.1) self["__cameraTweaks"]["tweaks"]["offset"]["value"].setInput( self["normalOffset"]) self["__cameraTweaksFilter"] = GafferScene.PathFilter() self["__cameraTweaksFilter"]["paths"].setValue( IECore.StringVectorData(['/camera'])) self["__cameraTweaks"]["filter"].setInput( self["__cameraTweaksFilter"]["out"]) self["__collectScenes"] = GafferScene.CollectScenes() self["__collectScenes"]["sourceRoot"].setValue("/camera") self["__collectScenes"]["rootNameVariable"].setValue( "collect:cameraName") self["__collectScenes"]["in"].setInput( self["__cameraTweaks"]["out"]) self["__group"] = GafferScene.Group() self["__group"]["in"][0].setInput(self["__collectScenes"]["out"]) self["__group"]["name"].setInput(self["cameraGroup"]) self["__parent"]["children"][0].setInput(self["__group"]["out"]) self["__collectSceneRootsExpression"] = Gaffer.Expression() self["__collectSceneRootsExpression"].setExpression( inspect.cleandoc(""" info = parent["__chunkedBakeInfo"] parent["__collectScenes"]["rootNames"] = IECore.StringVectorData( info.keys() ) """), "python") self["__cameraSetupExpression"] = Gaffer.Expression() self["__cameraSetupExpression"].setExpression( inspect.cleandoc(""" cameraName = context["collect:cameraName"] info = parent["__chunkedBakeInfo"] i = info[cameraName] udimOffset = i["udim"].value - 1001 parent["__cameraTweaks"]["tweaks"]["resolution"]["value"] = imath.V2i( i["resolution"].value ) parent["__cameraTweaks"]["tweaks"]["u_offset"]["value"] = -( udimOffset % 10 ) parent["__cameraTweaks"]["tweaks"]["v_offset"]["value"] = -( udimOffset / 10 ) parent["__cameraTweaks"]["tweaks"]["mesh"]["value"] = i["mesh"].value parent["__cameraTweaks"]["tweaks"]["uv_set"]["value"] = parent["uvSet"] if parent["uvSet"] != "uv" else "" """), "python") self["out"].setFlags(Gaffer.Plug.Flags.Serialisable, False) self["out"].setInput(self["__parent"]["out"])
def testPointAttributes( self ) : attr = self.testSetupAttributes() result = IECoreHoudini.FromHoudiniPolygonsConverter( attr ).convert() attr.parm("value1").set(123.456) self.assertEqual( result["test_attribute"].data.typeId(), IECore.TypeId.FloatVectorData ) self.assertTrue( result["test_attribute"].data[0] > 123.0 ) self.assertEqual( result["test_attribute"].data.size(), 100 ) self.assertEqual( result["test_attribute"].interpolation, IECoreScene.PrimitiveVariable.Interpolation.Vertex ) self.assertTrue( result.arePrimitiveVariablesValid() ) attr.parm("type").set(1) # integer result = IECoreHoudini.FromHoudiniPolygonsConverter( attr ).convert() self.assertEqual( result["test_attribute"].data.typeId(), IECore.TypeId.IntVectorData ) self.assertEqual( result["test_attribute"].data[0], 123 ) self.assertEqual( result["test_attribute"].data.size(), 100 ) self.assertEqual( result["test_attribute"].interpolation, IECoreScene.PrimitiveVariable.Interpolation.Vertex ) self.assertTrue( result.arePrimitiveVariablesValid() ) attr.parm("type").set(0) # float attr.parm("size").set(2) # 2 elementS attr.parm("value2").set(456.789) result = IECoreHoudini.FromHoudiniPolygonsConverter( attr ).convert() self.assertEqual( result["test_attribute"].data.typeId(), IECore.TypeId.V2fVectorData ) self.assertEqual( result["test_attribute"].data[0], imath.V2f( 123.456, 456.789 ) ) self.assertEqual( result["test_attribute"].data.size(), 100 ) self.assertEqual( result["test_attribute"].interpolation, IECoreScene.PrimitiveVariable.Interpolation.Vertex ) self.assertTrue( result.arePrimitiveVariablesValid() ) attr.parm("type").set(1) # int result = IECoreHoudini.FromHoudiniPolygonsConverter( attr ).convert() self.assertEqual( result["test_attribute"].data.typeId(), IECore.TypeId.V2iVectorData ) self.assertEqual( result["test_attribute"].data[0], imath.V2i( 123, 456 ) ) self.assertEqual( result["test_attribute"].data.size(), 100 ) self.assertEqual( result["test_attribute"].interpolation, IECoreScene.PrimitiveVariable.Interpolation.Vertex ) self.assertTrue( result.arePrimitiveVariablesValid() ) attr.parm("type").set(0) # float attr.parm("size").set(3) # 3 elements attr.parm("value3").set(999.999) result = IECoreHoudini.FromHoudiniPolygonsConverter( attr ).convert() self.assertEqual( result["test_attribute"].data.typeId(), IECore.TypeId.V3fVectorData ) self.assertEqual( result["test_attribute"].data[0],imath.V3f( 123.456, 456.789, 999.999 ) ) self.assertEqual( result["test_attribute"].data.size(), 100 ) self.assertEqual( result["test_attribute"].interpolation, IECoreScene.PrimitiveVariable.Interpolation.Vertex ) self.assertTrue( result.arePrimitiveVariablesValid() ) attr.parm("type").set(1) # int result = IECoreHoudini.FromHoudiniPolygonsConverter( attr ).convert() self.assertEqual( result["test_attribute"].data.typeId(), IECore.TypeId.V3iVectorData ) self.assertEqual( result["test_attribute"].data[0], imath.V3i( 123, 456, 999 ) ) self.assertEqual( result["test_attribute"].data.size(), 100 ) self.assertEqual( result["test_attribute"].interpolation, IECoreScene.PrimitiveVariable.Interpolation.Vertex ) self.assertTrue( result.arePrimitiveVariablesValid() ) attr.parm("type").set( 3 ) # string attr.parm( "string" ).setExpression("'string %06d!' % pwd().curPoint().number()", hou.exprLanguage.Python) result = IECoreHoudini.FromHoudiniPointsConverter( attr ).convert() self.assertEqual( result["test_attribute"].data.typeId(), IECore.TypeId.StringVectorData ) self.assertEqual( result["test_attribute"].data[10], "string 000010!" ) self.assertEqual( result["test_attribute"].data.size(), 100 ) self.assertEqual( result["test_attribute"].interpolation, IECoreScene.PrimitiveVariable.Interpolation.Vertex ) self.assertEqual( result["test_attribute"].indices[10], 10 ) self.assertEqual( result["test_attribute"].indices.size(), 100 ) self.assertTrue( result.arePrimitiveVariablesValid() )
def testMerging(self): allFilter = GafferScene.PathFilter() allFilter["paths"].setValue(IECore.StringVectorData(['/...'])) plane = GafferScene.Plane() plane["divisions"].setValue(imath.V2i(20, 20)) # Assign a basic gradient shader uvGradientCode = GafferOSL.OSLCode() uvGradientCode["out"].addChild( Gaffer.Color3fPlug("out", direction=Gaffer.Plug.Direction.Out)) uvGradientCode["code"].setValue('out = color( u, v, 0.5 );') shaderAssignment = GafferScene.ShaderAssignment() shaderAssignment["in"].setInput(plane["out"]) shaderAssignment["filter"].setInput(allFilter["out"]) shaderAssignment["shader"].setInput(uvGradientCode["out"]["out"]) # Set up a random id from 0 - 3 on each face randomCode = GafferOSL.OSLCode() randomCode["out"].addChild( Gaffer.IntPlug("randomId", direction=Gaffer.Plug.Direction.Out)) randomCode["code"].setValue( 'randomId = int(cellnoise( P * 100 ) * 4);') outInt = GafferOSL.OSLShader() outInt.loadShader("ObjectProcessing/OutInt") outInt["parameters"]["name"].setValue('randomId') outInt["parameters"]["value"].setInput(randomCode["out"]["randomId"]) outObject = GafferOSL.OSLShader() outObject.loadShader("ObjectProcessing/OutObject") outObject["parameters"]["in0"].setInput( outInt["out"]["primitiveVariable"]) oSLObject = GafferOSL.OSLObject() oSLObject["in"].setInput(shaderAssignment["out"]) oSLObject["filter"].setInput(allFilter["out"]) oSLObject["shader"].setInput(outObject["out"]) oSLObject["interpolation"].setValue(2) # Create 4 meshes by picking each of the 4 ids deleteContextVariables = Gaffer.DeleteContextVariables() deleteContextVariables.setup(GafferScene.ScenePlug()) deleteContextVariables["variables"].setValue('collect:rootName') deleteContextVariables["in"].setInput(oSLObject["out"]) pickCode = GafferOSL.OSLCode() pickCode["parameters"].addChild(Gaffer.IntPlug("targetId")) pickCode["out"].addChild( Gaffer.IntPlug("cull", direction=Gaffer.Plug.Direction.Out)) pickCode["code"].setValue( 'int randomId; getattribute( "randomId", randomId ); cull = randomId != targetId;' ) expression = Gaffer.Expression() pickCode.addChild(expression) expression.setExpression( 'parent.parameters.targetId = stoi( context( "collect:rootName", "0" ) );', "OSL") outInt1 = GafferOSL.OSLShader() outInt1.loadShader("ObjectProcessing/OutInt") outInt1["parameters"]["name"].setValue('deleteFaces') outInt1["parameters"]["value"].setInput(pickCode["out"]["cull"]) outObject1 = GafferOSL.OSLShader() outObject1.loadShader("ObjectProcessing/OutObject") outObject1["parameters"]["in0"].setInput( outInt1["out"]["primitiveVariable"]) oSLObject1 = GafferOSL.OSLObject() oSLObject1["in"].setInput(deleteContextVariables["out"]) oSLObject1["filter"].setInput(allFilter["out"]) oSLObject1["shader"].setInput(outObject1["out"]) oSLObject1["interpolation"].setValue(2) deleteFaces = GafferScene.DeleteFaces() deleteFaces["in"].setInput(oSLObject1["out"]) deleteFaces["filter"].setInput(allFilter["out"]) collectScenes = GafferScene.CollectScenes() collectScenes["in"].setInput(deleteFaces["out"]) collectScenes["rootNames"].setValue( IECore.StringVectorData(['0', '1', '2', '3'])) collectScenes["sourceRoot"].setValue('/plane') # First variant: bake everything, covering the whole 1001 UDIM customAttributes1 = GafferScene.CustomAttributes() customAttributes1["attributes"].addMember( 'bake:fileName', IECore.StringData( '${bakeDirectory}/complete/<AOV>/<AOV>.<UDIM>.exr')) customAttributes1["in"].setInput(collectScenes["out"]) # Second vaiant: bake just 2 of the 4 meshes, leaving lots of holes that will need filling pruneFilter = GafferScene.PathFilter() pruneFilter["paths"].setValue(IECore.StringVectorData(['/2', '/3'])) prune = GafferScene.Prune() prune["in"].setInput(collectScenes["out"]) prune["filter"].setInput(pruneFilter["out"]) customAttributes2 = GafferScene.CustomAttributes() customAttributes2["attributes"].addMember( 'bake:fileName', IECore.StringData( '${bakeDirectory}/incomplete/<AOV>/<AOV>.<UDIM>.exr')) customAttributes2["in"].setInput(prune["out"]) # Third variant: bake everything, but with one mesh at a higher resolution customAttributes3 = GafferScene.CustomAttributes() customAttributes3["attributes"].addMember( 'bake:fileName', IECore.StringData( '${bakeDirectory}/mismatch/<AOV>/<AOV>.<UDIM>.exr')) customAttributes3["in"].setInput(collectScenes["out"]) pathFilter2 = GafferScene.PathFilter() pathFilter2["paths"].setValue(IECore.StringVectorData(['/2'])) customAttributes = GafferScene.CustomAttributes() customAttributes["attributes"].addMember('bake:resolution', IECore.IntData(200)) customAttributes["filter"].setInput(pathFilter2["out"]) customAttributes["in"].setInput(customAttributes3["out"]) # Merge the 3 variants mergeGroup = GafferScene.Group() mergeGroup["in"][-1].setInput(customAttributes["out"]) mergeGroup["in"][-1].setInput(customAttributes1["out"]) mergeGroup["in"][-1].setInput(customAttributes2["out"]) arnoldTextureBake = GafferArnold.ArnoldTextureBake() arnoldTextureBake["in"].setInput(mergeGroup["out"]) arnoldTextureBake["filter"].setInput(allFilter["out"]) arnoldTextureBake["bakeDirectory"].setValue(self.temporaryDirectory() + '/bakeMerge/') arnoldTextureBake["defaultResolution"].setValue(128) # We want to check the intermediate results arnoldTextureBake["cleanupIntermediateFiles"].setValue(False) # Dispatch the bake script = Gaffer.ScriptNode() script.addChild(arnoldTextureBake) dispatcher = GafferDispatch.LocalDispatcher() dispatcher["jobsDirectory"].setValue(self.temporaryDirectory()) dispatcher.dispatch([arnoldTextureBake]) # Check results imageReader = GafferImage.ImageReader() outLayer = GafferOSL.OSLShader() outLayer.loadShader("ImageProcessing/OutLayer") outLayer["parameters"]["layerColor"].setInput( uvGradientCode["out"]["out"]) outImage = GafferOSL.OSLShader() outImage.loadShader("ImageProcessing/OutImage") outImage["parameters"]["in0"].setInput(outLayer["out"]["layer"]) oSLImage = GafferOSL.OSLImage() oSLImage["in"].setInput(imageReader["out"]) oSLImage["shader"].setInput(outImage["out"]) merge3 = GafferImage.Merge() merge3["in"]["in0"].setInput(oSLImage["out"]) merge3["in"]["in1"].setInput(imageReader["out"]) merge3["operation"].setValue(10) edgeDetect = self.SimpleEdgeDetect() edgeDetect["in"].setInput(imageReader["out"]) edgeStats = GafferImage.ImageStats() edgeStats["in"].setInput(edgeDetect["out"]) refDiffStats = GafferImage.ImageStats() refDiffStats["in"].setInput(merge3["out"]) oneLayerReader = GafferImage.ImageReader() grade = GafferImage.Grade() grade["in"].setInput(oneLayerReader["out"]) grade["channels"].setValue('[A]') grade["blackPoint"].setValue(imath.Color4f(0, 0, 0, 0.999899983)) copyChannels = GafferImage.CopyChannels() copyChannels["in"]["in0"].setInput(merge3["out"]) copyChannels["in"]["in1"].setInput(grade["out"]) copyChannels["channels"].setValue('[A]') premultiply = GafferImage.Premultiply() premultiply["in"].setInput(copyChannels["out"]) refDiffCoveredStats = GafferImage.ImageStats() refDiffCoveredStats["in"].setInput(premultiply["out"]) # We are testing 3 different cases: # complete : Should be an exact match. # incomplete : Expect some mild variance of slopes and some error, because we have to # reconstruct a lot of missing data. # mismatch : We should get a larger image, sized to the highest override on any mesh. # Match won't be as perfect, because we're combining source images at # different resolutions for name, expectedSize, maxEdge, maxRefDiff, maxMaskedDiff in [ ("complete", 128, 0.01, 0.000001, 0.000001), ("incomplete", 128, 0.05, 0.15, 0.000001), ("mismatch", 200, 0.01, 0.01, 0.01) ]: imageReader["fileName"].setValue(self.temporaryDirectory() + "/bakeMerge/" + name + "/beauty/beauty.1001.tx") oneLayerReader["fileName"].setValue(self.temporaryDirectory() + "/bakeMerge/" + name + "/beauty/beauty.1001.exr") self.assertEqual(imageReader["out"]["format"].getValue().width(), expectedSize) self.assertEqual(imageReader["out"]["format"].getValue().height(), expectedSize) edgeStats["area"].setValue( imath.Box2i(imath.V2i(1), imath.V2i(expectedSize - 1))) refDiffStats["area"].setValue( imath.Box2i(imath.V2i(1), imath.V2i(expectedSize - 1))) refDiffCoveredStats["area"].setValue( imath.Box2i(imath.V2i(0), imath.V2i(expectedSize))) # Blue channel is constant, so everything should line up perfectly self.assertEqual(0, edgeStats["max"].getValue()[2]) self.assertEqual(0, refDiffStats["max"].getValue()[2]) self.assertEqual(0, refDiffCoveredStats["max"].getValue()[2]) for i in range(2): # Make sure we've got actual data, by checking that we have some error ( we're not expecting # to perfectly reconstruct the gradient when the input is incomplete ) self.assertGreater(edgeStats["max"].getValue()[i], 0.005) if name == "incomplete": self.assertGreater(edgeStats["max"].getValue()[i], 0.03) self.assertGreater(refDiffStats["max"].getValue()[i], 0.06) self.assertLess(edgeStats["max"].getValue()[i], maxEdge) self.assertLess(refDiffStats["max"].getValue()[i], maxRefDiff) self.assertLess(refDiffCoveredStats["max"].getValue()[i], maxMaskedDiff)
which the `paths` are relative to. This can be useful when working on a single asset in isolation, and then placing it into multiple locations within a layout. When no filter is connected, all `paths` are treated as being relative to `/`, the true scene root. """, "plugValueWidget:type", "", ], }) ########################################################################## # NodeGadget drop handler ########################################################################## GafferUI.Pointer.registerPointer( "addObjects", GafferUI.Pointer("addObjects.png", imath.V2i(36, 18))) GafferUI.Pointer.registerPointer( "removeObjects", GafferUI.Pointer("removeObjects.png", imath.V2i(36, 18))) GafferUI.Pointer.registerPointer( "replaceObjects", GafferUI.Pointer("replaceObjects.png", imath.V2i(36, 18))) __DropMode = IECore.Enum.create("None", "Add", "Remove", "Replace") __originalDragPointer = None def __pathsPlug(node): for plug in node.children(Gaffer.Plug): if Gaffer.Metadata.value(plug, "ui:scene:acceptsPaths"):
def mesh( self ) : vertsPerFace = IECore.IntVectorData( [ 4, 4, 4, 4, 4, 4 ] ) vertexIds = IECore.IntVectorData( [ 1, 5, 4, 0, 2, 6, 5, 1, 3, 7, 6, 2, 0, 4, 7, 3, 2, 1, 0, 3, 5, 6, 7, 4 ] ) mesh = IECoreScene.MeshPrimitive( vertsPerFace, vertexIds ) floatData = IECore.FloatData( 1.5 ) v2fData = IECore.V2fData( imath.V2f( 1.5, 2.5 ), IECore.GeometricData.Interpretation.Vector ) v3fData = IECore.V3fData( imath.V3f( 1.5, 2.5, 3.5 ) ) color3fData = IECore.Color3fData( imath.Color3f( 1.5, 2.5, 3.5 ) ) intData = IECore.IntData( 1 ) v2iData = IECore.V2iData( imath.V2i( 1, 2 ) ) v3iData = IECore.V3iData( imath.V3i( 1, 2, 3 ) ) stringData = IECore.StringData( "this is a string" ) intRange = range( 1, 25 ) floatVectorData = IECore.FloatVectorData( [ x+0.5 for x in intRange ] ) v2fVectorData = IECore.V2fVectorData( [ imath.V2f( x, x+0.5 ) for x in intRange ] ) v3fVectorData = IECore.V3fVectorData( [ imath.V3f( x, x+0.5, x+0.75 ) for x in intRange ], IECore.GeometricData.Interpretation.Normal ) color3fVectorData = IECore.Color3fVectorData( [ imath.Color3f( x, x+0.5, x+0.75 ) for x in intRange ] ) intVectorData = IECore.IntVectorData( intRange ) v2iVectorData = IECore.V2iVectorData( [ imath.V2i( x, -x ) for x in intRange ] ) v3iVectorData = IECore.V3iVectorData( [ imath.V3i( x, -x, x*2 ) for x in intRange ] ) stringVectorData = IECore.StringVectorData( [ "string number %06d!" % x for x in intRange ] ) detailInterpolation = IECoreScene.PrimitiveVariable.Interpolation.Constant pointInterpolation = IECoreScene.PrimitiveVariable.Interpolation.Vertex primitiveInterpolation = IECoreScene.PrimitiveVariable.Interpolation.Uniform vertexInterpolation = IECoreScene.PrimitiveVariable.Interpolation.FaceVarying # add all valid detail attrib types mesh["floatDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, floatData ) mesh["v2fDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, v2fData ) mesh["v3fDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, v3fData ) mesh["color3fDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, color3fData ) mesh["intDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, intData ) mesh["v2iDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, v2iData ) mesh["v3iDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, v3iData ) mesh["stringDetail"] = IECoreScene.PrimitiveVariable( detailInterpolation, stringData ) # add all valid point attrib types pData = IECore.V3fVectorData( [ imath.V3f( 0, 1, 2 ), imath.V3f( 1 ), imath.V3f( 2 ), imath.V3f( 3 ), imath.V3f( 4 ), imath.V3f( 5 ), imath.V3f( 6 ), imath.V3f( 7 ), ], IECore.GeometricData.Interpretation.Point ) mesh["P"] = IECoreScene.PrimitiveVariable( pointInterpolation, pData ) mesh["floatPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, floatVectorData[:8] ) mesh["v2fPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, v2fVectorData[:8] ) mesh["v3fPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, v3fVectorData[:8] ) mesh["color3fPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, color3fVectorData[:8] ) mesh["intPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, intVectorData[:8] ) mesh["v2iPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, v2iVectorData[:8] ) mesh["v3iPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, v3iVectorData[:8] ) mesh["stringPoint"] = IECoreScene.PrimitiveVariable( pointInterpolation, stringVectorData[:8], IECore.IntVectorData( range( 0, 8 ) ) ) # add all valid primitive attrib types mesh["floatPrim"] = IECoreScene.PrimitiveVariable( primitiveInterpolation, floatVectorData[:6] ) mesh["v2fPrim"] = IECoreScene.PrimitiveVariable( primitiveInterpolation, v2fVectorData[:6] ) mesh["v3fPrim"] = IECoreScene.PrimitiveVariable( primitiveInterpolation, v3fVectorData[:6] ) mesh["color3fPrim"] = IECoreScene.PrimitiveVariable( primitiveInterpolation, color3fVectorData[:6] ) mesh["intPrim"] = IECoreScene.PrimitiveVariable( primitiveInterpolation, intVectorData[:6] ) mesh["v2iPrim"] = IECoreScene.PrimitiveVariable( primitiveInterpolation, v2iVectorData[:6] ) mesh["v3iPrim"] = IECoreScene.PrimitiveVariable( primitiveInterpolation, v3iVectorData[:6] ) mesh["stringPrim"] = IECoreScene.PrimitiveVariable( primitiveInterpolation, stringVectorData[:6], IECore.IntVectorData( range( 0, 6 ) ) ) # add all valid vertex attrib types mesh["floatVert"] = IECoreScene.PrimitiveVariable( vertexInterpolation, floatVectorData ) mesh["v2fVert"] = IECoreScene.PrimitiveVariable( vertexInterpolation, v2fVectorData ) mesh["v3fVert"] = IECoreScene.PrimitiveVariable( vertexInterpolation, v3fVectorData ) mesh["color3fVert"] = IECoreScene.PrimitiveVariable( vertexInterpolation, color3fVectorData ) mesh["intVert"] = IECoreScene.PrimitiveVariable( vertexInterpolation, intVectorData ) mesh["v2iVert"] = IECoreScene.PrimitiveVariable( vertexInterpolation, v2iVectorData ) mesh["v3iVert"] = IECoreScene.PrimitiveVariable( vertexInterpolation, v3iVectorData ) mesh["stringVert"] = IECoreScene.PrimitiveVariable( vertexInterpolation, stringVectorData, IECore.IntVectorData( range( 0, 24 ) ) ) return mesh
def __init__(self, imageView, **kw): GafferUI.Spacer.__init__(self, size=imath.V2i(0, 25))
import imath import Gaffer import GafferScene # User defaults are applied automatically whenever a node is created by the user through the UI. Gaffer.Metadata.registerValue(GafferScene.Sphere, "radius", "userDefault", 100.0) Gaffer.Metadata.registerValue(GafferScene.StandardOptions, "options.renderResolution.value", "userDefault", imath.V2i(2048, 1556))
def testPythonExpressionAndGIL(self): script = Gaffer.ScriptNode() script["plane"] = GafferScene.Plane() script["plane"]["divisions"].setValue(imath.V2i(20)) script["sphere"] = GafferScene.Sphere() script["expression"] = Gaffer.Expression() script["expression"].setExpression( "parent['sphere']['radius'] = context.getFrame()") script["instancer"] = GafferScene.Instancer() script["instancer"]["in"].setInput(script["plane"]["out"]) script["instancer"]["instances"].setInput(script["sphere"]["out"]) script["instancer"]["parent"].setValue("/plane") # The Instancer spawns its own threads, so if we don't release the GIL # when invoking it, and an upstream node enters Python, we'll end up # with a deadlock. Test that isn't the case. We increment the frame # between each test to ensure the expression result is not cached and # we do truly enter python. with Gaffer.Context() as c: c["scene:path"] = IECore.InternedStringVectorData(["plane"]) c.setFrame(1) script["instancer"]["out"]["globals"].getValue() c.setFrame(2) script["instancer"]["out"]["bound"].getValue() c.setFrame(3) script["instancer"]["out"]["transform"].getValue() c.setFrame(4) script["instancer"]["out"]["object"].getValue() c.setFrame(5) script["instancer"]["out"]["attributes"].getValue() c.setFrame(6) script["instancer"]["out"]["childNames"].getValue() c.setFrame(7) c.setFrame(101) script["instancer"]["out"]["globals"].hash() c.setFrame(102) script["instancer"]["out"]["bound"].hash() c.setFrame(103) script["instancer"]["out"]["transform"].hash() c.setFrame(104) script["instancer"]["out"]["object"].hash() c.setFrame(105) script["instancer"]["out"]["attributes"].hash() c.setFrame(106) script["instancer"]["out"]["childNames"].hash() c.setFrame(107) # The same applies for the higher level helper functions on ScenePlug c.setFrame(200) script["instancer"]["out"].bound("/plane") c.setFrame(201) script["instancer"]["out"].transform("/plane") c.setFrame(202) script["instancer"]["out"].fullTransform("/plane") c.setFrame(203) script["instancer"]["out"].attributes("/plane") c.setFrame(204) script["instancer"]["out"].fullAttributes("/plane") c.setFrame(205) script["instancer"]["out"].object("/plane") c.setFrame(206) script["instancer"]["out"].childNames("/plane") c.setFrame(207) c.setFrame(300) script["instancer"]["out"].boundHash("/plane") c.setFrame(301) script["instancer"]["out"].transformHash("/plane") c.setFrame(302) script["instancer"]["out"].fullTransformHash("/plane") c.setFrame(303) script["instancer"]["out"].attributesHash("/plane") c.setFrame(304) script["instancer"]["out"].fullAttributesHash("/plane") c.setFrame(305) script["instancer"]["out"].objectHash("/plane") c.setFrame(306) script["instancer"]["out"].childNamesHash("/plane") c.setFrame(307)
def testConstruction( self ): idd = IECoreImage.ImageDisplayDriver( imath.Box2i( imath.V2i(0,0), imath.V2i(100,100) ), imath.Box2i( imath.V2i(10,10), imath.V2i(40,40) ), [ 'r','g','b' ], IECore.CompoundData() ) self.assertEqual( idd.scanLineOrderOnly(), False ) self.assertEqual( idd.displayWindow(), imath.Box2i( imath.V2i(0,0), imath.V2i(100,100) ) ) self.assertEqual( idd.dataWindow(), imath.Box2i( imath.V2i(10,10), imath.V2i(40,40) ) ) self.assertEqual( idd.channelNames(), [ 'r', 'g', 'b' ] )
def testFactory(self): # mesh m = IECoreScene.MeshPrimitive.createPlane( imath.Box2f(imath.V2f(-1), imath.V2f(1))) c = IECoreGL.ToGLConverter.create(m) self.failUnless(isinstance(c, IECoreGL.ToGLMeshConverter)) c = IECoreGL.ToGLConverter.create(m, IECoreGL.Primitive.staticTypeId()) self.failUnless(isinstance(c, IECoreGL.ToGLMeshConverter)) c = IECoreGL.ToGLConverter.create(m, IECoreGL.Texture.staticTypeId()) self.assertEqual(c, None) # points p = IECoreScene.PointsPrimitive(10) c = IECoreGL.ToGLConverter.create(p) self.failUnless(isinstance(c, IECoreGL.ToGLPointsConverter)) c = IECoreGL.ToGLConverter.create(p, IECoreGL.Primitive.staticTypeId()) self.failUnless(isinstance(c, IECoreGL.ToGLPointsConverter)) c = IECoreGL.ToGLConverter.create(p, IECoreGL.Texture.staticTypeId()) self.assertEqual(c, None) # curves cv = IECoreScene.CurvesPrimitive() c = IECoreGL.ToGLConverter.create(cv) self.failUnless(isinstance(c, IECoreGL.ToGLCurvesConverter)) c = IECoreGL.ToGLConverter.create(cv, IECoreGL.Primitive.staticTypeId()) self.failUnless(isinstance(c, IECoreGL.ToGLCurvesConverter)) c = IECoreGL.ToGLConverter.create(cv, IECoreGL.Texture.staticTypeId()) self.assertEqual(c, None) # splines spline = IECore.SplinefColor3fData( IECore.SplinefColor3f( IECore.CubicBasisf.catmullRom(), ( (0, imath.Color3f(1)), (0, imath.Color3f(1)), (1, imath.Color3f(0)), (1, imath.Color3f(0)), ), ), ) c = IECoreGL.ToGLConverter.create(spline) self.failUnless(isinstance(c, IECoreGL.SplineToGLTextureConverter)) spline = IECore.SplinefColor4fData( IECore.SplinefColor4f( IECore.CubicBasisf.catmullRom(), ( (0, imath.Color4f(1)), (0, imath.Color4f(1)), (1, imath.Color4f(0)), (1, imath.Color4f(0)), ), ), ) c = IECoreGL.ToGLConverter.create(spline) self.failUnless(isinstance(c, IECoreGL.SplineToGLTextureConverter)) spline = IECore.SplineffData( IECore.Splineff( IECore.CubicBasisf.catmullRom(), ( (0, 1), (0, 1), (1, 0), (1, 0), ), ), ) c = IECoreGL.ToGLConverter.create(spline) self.failUnless(isinstance(c, IECoreGL.SplineToGLTextureConverter)) # images image = IECoreImage.ImagePrimitive.createRGBFloat( imath.Color3f(1, 0, 0), imath.Box2i(imath.V2i(256), ), imath.Box2i(imath.V2i(256))) c = IECoreGL.ToGLConverter.create(image) self.failUnless(isinstance(c, IECoreGL.ToGLTextureConverter)) # compound data compoundData = IECore.CompoundData({ "dataWindow": IECore.Box2iData(image.dataWindow), "displayWindow": IECore.Box2iData(image.displayWindow), "channels": { "R": image["R"], "G": image["G"], "B": image["B"], } }) c = IECoreGL.ToGLConverter.create(compoundData) self.failUnless(isinstance(c, IECoreGL.ToGLTextureConverter))