From f59ed1b8dce1a07f44f46f4ac8f3ade9ff5705cc Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Mon, 8 Dec 2025 15:23:01 -0800 Subject: [PATCH 01/11] Update Cortex dependency version to 10.7.0.0a1 --- .github/workflows/main/installDependencies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main/installDependencies.py b/.github/workflows/main/installDependencies.py index bf5e91ea03..3a95baf5c8 100755 --- a/.github/workflows/main/installDependencies.py +++ b/.github/workflows/main/installDependencies.py @@ -49,7 +49,7 @@ # Determine default archive URL. -defaultURL = "https://github.com/ImageEngine/cortex/releases/download/10.6.2.1/cortex-10.6.2.1-{platform}{buildEnvironment}.{extension}" +defaultURL = "https://github.com/ImageEngine/cortex/releases/download/10.7.0.0a1/cortex-10.7.0.0a1-{platform}{buildEnvironment}.{extension}" # Parse command line arguments. From 77cf56a684bec350db1ce8a4cd24b575a998467b Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Mon, 3 Nov 2025 18:52:34 -0800 Subject: [PATCH 02/11] IECoreDelightTest : Fix incorrect test Linear splines in OSL only need 1 extra endpoint. This test had linear splines with 2 extra endpoints, because it started from a Cortex representation that already had an extra endpoint - that's conceptually wrong, IECore::Spline only uses duplicate end points for curve types where it is required for evaluation, not for linear. --- python/IECoreDelightTest/RendererTest.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/python/IECoreDelightTest/RendererTest.py b/python/IECoreDelightTest/RendererTest.py index 3b38357e32..f7c4aa4289 100644 --- a/python/IECoreDelightTest/RendererTest.py +++ b/python/IECoreDelightTest/RendererTest.py @@ -1006,8 +1006,6 @@ def test3DelightSplineParameters( self ) : IECore.CubicBasisf.linear(), [ ( 0, 0.25 ), - ( 0, 0.25 ), - ( 1, 0.75 ), ( 1, 0.75 ), ] ), @@ -1024,8 +1022,6 @@ def test3DelightSplineParameters( self ) : IECore.CubicBasisf.linear(), [ ( 0, 0.25 ), - ( 0, 0.25 ), - ( 1, 0.75 ), ( 1, 0.75 ), ] ), @@ -1093,9 +1089,9 @@ def test3DelightSplineParameters( self ) : self.assertNotIn( "colorSplineValues", shader ) self.assertNotIn( "colorSplineBasis", shader ) - self.assertEqual( shader["dualInterpolationSpline_Knots"], [ 0, 0, 0, 1, 1, 1 ] ) - self.assertEqual( shader["dualInterpolationSpline_Floats"], [ 0.25, 0.25, 0.25, 0.75, 0.75, 0.75 ] ) - self.assertEqual( shader["dualInterpolationSpline_Interp"], [ 1, 1, 1, 1, 1, 1 ] ) + self.assertEqual( shader["dualInterpolationSpline_Knots"], [ 0, 0, 1, 1 ] ) + self.assertEqual( shader["dualInterpolationSpline_Floats"], [ 0.25, 0.25, 0.75, 0.75 ] ) + self.assertEqual( shader["dualInterpolationSpline_Interp"], [ 1, 1, 1, 1 ] ) self.assertNotIn( "dualInterpolationSplinePositions", shader ) self.assertNotIn( "dualInterpolationSplineValues", shader ) @@ -1111,9 +1107,9 @@ def test3DelightSplineParameters( self ) : self.assertNotIn( "trimmedFloatSplineValues", shader ) self.assertNotIn( "trimmedFloatSplineBasis", shader ) - self.assertEqual( shader["mayaSpline_Knots"], [ 0, 0, 0, 1, 1, 1 ] ) - self.assertEqual( shader["mayaSpline_Floats"], [ 0.25, 0.25, 0.25, 0.75, 0.75, 0.75 ] ) - self.assertEqual( shader["mayaSpline_Interp"], [ 1, 1, 1, 1, 1, 1 ] ) + self.assertEqual( shader["mayaSpline_Knots"], [ 0, 0, 1, 1 ] ) + self.assertEqual( shader["mayaSpline_Floats"], [ 0.25, 0.25, 0.75, 0.75 ] ) + self.assertEqual( shader["mayaSpline_Interp"], [ 1, 1, 1, 1 ] ) self.assertNotIn( "mayaSplinePositions", shader ) self.assertNotIn( "maysSplineValues", shader ) From 89a6c7b07d1706ce6d8bf0cc63bb6ac1566b9c46 Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Wed, 26 Nov 2025 09:58:14 -0800 Subject: [PATCH 03/11] IECoreDelight::ShaderNetworkAlgo : Use convertToOSLConventions Previously, connections to color components in OSL shaders would fail in 3Delight --- src/IECoreDelight/ShaderNetworkAlgo.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/IECoreDelight/ShaderNetworkAlgo.cpp b/src/IECoreDelight/ShaderNetworkAlgo.cpp index f588f3624f..c69fe02e38 100644 --- a/src/IECoreDelight/ShaderNetworkAlgo.cpp +++ b/src/IECoreDelight/ShaderNetworkAlgo.cpp @@ -1014,11 +1014,16 @@ ShaderNetworkPtr preprocessedNetwork( const ShaderNetwork *shaderNetwork ) { ShaderNetworkPtr result = shaderNetwork->copy(); - IECoreScene::ShaderNetworkAlgo::expandSplines( result.get() ); + // Technically, this should be the OSL version used by 3Delight, rather than currently being the + // OSL version we are compiled with. However, currently the only test on OSL version is whether it + // is newer than 1.10, which should currently always be true, so this doesn't really matter. If a + // future OSL version introduces a new feature we want to take advantage of in this function, we + // may need to put some extra work into getting 3delight's OSL version here. + IECoreScene::ShaderNetworkAlgo::convertToOSLConventions( result.get(), OSL_VERSION ); // IECoreScene::ShaderNetworkAlgo tries to expand splines according to the correct naming convention // ... but 3delight doesn't have a consistent naming convention, and we have to do shader queries of - // the original OSL shaders to try and figure out what names to use. expandSplines doesn't do that, + // the original OSL shaders to try and figure out what names to use. convertToOSLConventions doesn't do that, // so it just uses the Gaffer naming convention, and we rename the parameters if we're able to find // the correct naming convention. renameSplineParameters( result.get() ); From 948e506e323130ad1ff529fa24de21358f0bf30e Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 25 Nov 2025 15:07:31 -0800 Subject: [PATCH 04/11] Update type blacklists to support building against Cortex-10.7 --- src/Gaffer/TweakPlug.cpp | 1 + src/GafferScene/IECoreScenePreview/PrimitiveAlgo.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/Gaffer/TweakPlug.cpp b/src/Gaffer/TweakPlug.cpp index 231f80537f..d306c7da19 100644 --- a/src/Gaffer/TweakPlug.cpp +++ b/src/Gaffer/TweakPlug.cpp @@ -740,6 +740,7 @@ IECore::DataPtr TweakPlug::createVectorDataFromElement( const IECore::Data *elem // A bunch of things we're not allowed to make vectors of !IECore::TypeTraits::IsTransformationMatrix< ValueType >::value && !IECore::TypeTraits::IsSpline< ValueType >::value && + !IECore::TypeTraits::IsRamp< ValueType >::value && !std::is_same_v< ValueType, IECore::PathMatcher > && !std::is_same_v< ValueType, boost::posix_time::ptime > ) diff --git a/src/GafferScene/IECoreScenePreview/PrimitiveAlgo.cpp b/src/GafferScene/IECoreScenePreview/PrimitiveAlgo.cpp index 9617277e5b..8c1c45307f 100644 --- a/src/GafferScene/IECoreScenePreview/PrimitiveAlgo.cpp +++ b/src/GafferScene/IECoreScenePreview/PrimitiveAlgo.cpp @@ -104,6 +104,9 @@ constexpr bool supportsVectorTypedData() std::is_same_v< T, IECore::SplinefColor3f > || std::is_same_v< T, IECore::SplinefColor4f > || std::is_same_v< T, IECore::Splinedd > || + std::is_same_v< T, IECore::Rampff > || + std::is_same_v< T, IECore::RampfColor3f > || + std::is_same_v< T, IECore::RampfColor4f > || std::is_same_v< T, IECore::PathMatcher > || std::is_same_v< T, boost::posix_time::ptime> ); From c0dfc26d5678e98404d54dbf797d0aa3ca68e846 Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 25 Nov 2025 15:19:06 -0800 Subject: [PATCH 05/11] GafferImage::Ramp : Drop "using namespace IECore" to prevent conflict --- src/GafferImage/Ramp.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/GafferImage/Ramp.cpp b/src/GafferImage/Ramp.cpp index 2783872920..dd601b6d78 100644 --- a/src/GafferImage/Ramp.cpp +++ b/src/GafferImage/Ramp.cpp @@ -42,7 +42,6 @@ using namespace std; using namespace Imath; -using namespace IECore; using namespace GafferImage; using namespace Gaffer; @@ -205,7 +204,7 @@ IECore::ConstStringVectorDataPtr Ramp::computeChannelNames( const Gaffer::Contex channelNamePrefix += "."; } - StringVectorDataPtr resultData = new StringVectorData(); + IECore::StringVectorDataPtr resultData = new IECore::StringVectorData(); vector &result = resultData->writable(); result.push_back( channelNamePrefix + "R" ); @@ -237,7 +236,7 @@ IECore::ConstFloatVectorDataPtr Ramp::computeChannelData( const std::string &cha { const int channelIndex = ImageAlgo::colorIndex( context->get( ImagePlug::channelNameContextName ) ); - const SplinefColor4f ramp = rampPlug()->getValue().spline(); + const IECore::SplinefColor4f ramp = rampPlug()->getValue().spline(); const M33f inverseTransform = transformPlug()->matrix().inverse(); const V2f startPosition = startPositionPlug()->getValue(); @@ -246,9 +245,9 @@ IECore::ConstFloatVectorDataPtr Ramp::computeChannelData( const std::string &cha V3f startPosition3f( startPosition.x, startPosition.y, 0 ); V3f endPosition3f( endPosition.x, endPosition.y, 0 ); - const LineSegment3f line( startPosition3f, endPosition3f ); + const IECore::LineSegment3f line( startPosition3f, endPosition3f ); - FloatVectorDataPtr resultData = new FloatVectorData; + IECore::FloatVectorDataPtr resultData = new IECore::FloatVectorData; vector &result = resultData->writable(); result.reserve( ImagePlug::tileSize() * ImagePlug::tileSize() ); From ea7d45fa4f6aa0d97700a02cf2aa4aa0360e0b4d Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 18 Nov 2025 15:39:43 -0800 Subject: [PATCH 06/11] IECoreArnold : Remove deprecated/dupe call to expandSplineParameters IECoreScene::ShaderNetworkAlgo::expandSplineParameters was the deprecated way to handle spline parameters. IECoreArnold::ShaderNetworkAlgo is now doing the up to date approach - there is a call to IECoreScene::ShaderNetworkAlgo::convertToOSLConventions in preprocessedNetwork, which will have already converted splines. As far as I can tell, this means that expandSplineParameters was currently not doing anything, and the fact it was still being called was simply an oversight. --- src/IECoreArnold/ShaderNetworkAlgo.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/IECoreArnold/ShaderNetworkAlgo.cpp b/src/IECoreArnold/ShaderNetworkAlgo.cpp index f392ea489d..1b9b26a2ca 100644 --- a/src/IECoreArnold/ShaderNetworkAlgo.cpp +++ b/src/IECoreArnold/ShaderNetworkAlgo.cpp @@ -136,11 +136,7 @@ AtNode *convertWalk( const ShaderNetwork::Parameter &outputParameter, const IECo // Set the shader parameters - IECore::ConstCompoundDataPtr expandedParameters = IECoreScene::ShaderNetworkAlgo::expandSplineParameters( - shader->parametersData() - ); - - for( const auto &namedParameter : expandedParameters->readable() ) + for( const auto &namedParameter : shader->parametersData()->readable() ) { string parameterName; if( isOSLShader ) From 1cefa291be6ed41083edcc7177566926504753ee Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 25 Nov 2025 15:37:24 -0800 Subject: [PATCH 07/11] IECoreRenderMan : IECoreScene::ShaderNetworkAlgo::expandRamps renamed --- src/IECoreRenderMan/ShaderNetworkAlgo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IECoreRenderMan/ShaderNetworkAlgo.cpp b/src/IECoreRenderMan/ShaderNetworkAlgo.cpp index 7be2f2d4f3..abd8f4e85f 100644 --- a/src/IECoreRenderMan/ShaderNetworkAlgo.cpp +++ b/src/IECoreRenderMan/ShaderNetworkAlgo.cpp @@ -756,7 +756,7 @@ ShaderNetworkPtr preprocessedNetwork( const IECoreScene::ShaderNetwork *shaderNe correctParameters( result.get() ); - IECoreScene::ShaderNetworkAlgo::expandSplines( result.get() ); + IECoreScene::ShaderNetworkAlgo::expandRamps( result.get() ); IECoreRenderMan::ShaderNetworkAlgo::convertUSDShaders( result.get() ); From 41b8aa9cc2d92c25729d8321bbc3145fcc0952d6 Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 28 Oct 2025 15:52:23 -0700 Subject: [PATCH 08/11] SplinePlug : Remove old compatibility config --- Changes.md | 2 + python/GafferTest/ExpressionTest.py | 4 +- startup/Gaffer/splinePlugCompatibility.py | 114 ---------------------- 3 files changed, 4 insertions(+), 116 deletions(-) delete mode 100644 startup/Gaffer/splinePlugCompatibility.py diff --git a/Changes.md b/Changes.md index 493a183fc7..996ab22b16 100644 --- a/Changes.md +++ b/Changes.md @@ -20,6 +20,8 @@ Breaking Changes - RenderUI : Removed deprecated `rendererPresetNames()` function. - Menu : Removed support for `enter` and `leave` properties on menu items. - SceneEditor : Removed `numInputs` argument to `Settings` constructor. +- Gaffer::SplinePlug : + - Removed support for loading splines saved with Gaffer version 0.40.0.0 and earlier 1.6.x.x (relative to 1.6.7.0) ======= diff --git a/python/GafferTest/ExpressionTest.py b/python/GafferTest/ExpressionTest.py index d023cbe9db..26b3492fa3 100644 --- a/python/GafferTest/ExpressionTest.py +++ b/python/GafferTest/ExpressionTest.py @@ -1144,12 +1144,12 @@ def testNoDefaultExpressionForUnsupportedPlugs( self ) : s["n"] = Gaffer.Node() s["n"]["user"].addChild( Gaffer.SplineffPlug( - defaultValue = IECore.Splineff( - IECore.CubicBasisf.linear(), + defaultValue = Gaffer.SplineDefinitionff( ( ( 0, 0 ), ( 1, 1 ), ), + Gaffer.SplineDefinitionInterpolation.Linear ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) diff --git a/startup/Gaffer/splinePlugCompatibility.py b/startup/Gaffer/splinePlugCompatibility.py deleted file mode 100644 index 7da6ffd46a..0000000000 --- a/startup/Gaffer/splinePlugCompatibility.py +++ /dev/null @@ -1,114 +0,0 @@ -########################################################################## -# -# Copyright (c) 2017, Image Engine Design Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above -# copyright notice, this list of conditions and the following -# disclaimer. -# -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided with -# the distribution. -# -# * Neither the name of John Haddon nor the names of -# any other contributors to this software may be used to endorse or -# promote products derived from this software without specific prior -# written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -########################################################################## - -import Gaffer -import IECore - - -def __convertCortexSpline( spline, oldType, newType ): - if type( spline ) != oldType : - # Not the case we need to fix - return spline - - interpolation = None - if spline.basis == type( spline.basis ).linear(): - interpolation = Gaffer.SplineDefinitionInterpolation.Linear - elif spline.basis == type( spline.basis ).catmullRom(): - interpolation = Gaffer.SplineDefinitionInterpolation.CatmullRom - elif spline.basis == eval( repr( type( spline.basis ).bSpline() ) ): - # Note that serialising the bSpline basis alters it slightly due to floating point precision, - # so we have to compare to altered version - interpolation = Gaffer.SplineDefinitionInterpolation.BSpline - else: - raise Exception( "Error setting " + newType.__name__ + "- Unrecognized basis: " + repr( spline.basis ) ) - - result = newType( spline.points(), interpolation ) - if not result.trimEndPoints(): - raise Exception( "Error setting " + newType.__name__ + "- Could not convert: " + repr( spline ) ) - - return result - - - -def __initWrapper( originalInit, defaultName, oldValueType, valueType ): - - def init( self, name = defaultName, direction = Gaffer.Plug.Direction.In, - defaultValue = valueType(), flags = Gaffer.Plug.Flags.Default ): - - originalInit( self, name, direction, __convertCortexSpline( defaultValue, oldValueType, valueType ), flags ) - - return init - -Gaffer.SplineffPlug.__init__ = __initWrapper( Gaffer.SplineffPlug.__init__, "SplineffPlug", - IECore.Splineff, Gaffer.SplineDefinitionff ) -Gaffer.SplinefColor3fPlug.__init__ = __initWrapper( Gaffer.SplinefColor3fPlug.__init__, "SplinefColor3fPlug", - IECore.SplinefColor3f, Gaffer.SplineDefinitionfColor3f ) - -def __setValueWrapper( originalSetValue, oldValueType, valueType ): - - def setValue( self, value ): - - originalSetValue( self, __convertCortexSpline( value, oldValueType, valueType ) ) - - return setValue - -Gaffer.SplineffPlug.setValue = __setValueWrapper( Gaffer.SplineffPlug.setValue, - IECore.Splineff, Gaffer.SplineDefinitionff ) -Gaffer.SplinefColor3fPlug.setValue = __setValueWrapper( Gaffer.SplinefColor3fPlug.setValue, - IECore.SplinefColor3f, Gaffer.SplineDefinitionfColor3f ) - - -class __DummyIgnoreAllSetValuesRecursive( object ) : - - def setValue( self, value ) : - pass - - def __getitem__( self, item ) : - return self - -def __getitemWrapper( originalGetitem ): - - def getItem( self, item ): - - if item == "basis": - return __DummyIgnoreAllSetValuesRecursive() - else: - return originalGetitem( self, item ) - - return getItem - -Gaffer.SplineffPlug.__getitem__ = __getitemWrapper( Gaffer.SplineffPlug.__getitem__ ) -Gaffer.SplinefColor3fPlug.__getitem__ = __getitemWrapper( Gaffer.SplinefColor3fPlug.__getitem__ ) From d385ed1d03e421ccbc7764ff15b5d0471a4b59ca Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 25 Nov 2025 14:29:32 -0800 Subject: [PATCH 09/11] Rename ColorRamp and FloatRamp osl shaders --- Changes.md | 1 + python/GafferOSLTest/OSLShaderTest.py | 64 +++++++++++ shaders/Pattern/ColorRamp.osl | 112 +++++++++++++++++++ shaders/Pattern/ColorSpline.osl | 1 + shaders/Pattern/FloatRamp.osl | 112 +++++++++++++++++++ shaders/Pattern/FloatSpline.osl | 1 + startup/GafferOSL/shaderNameCompatibility.py | 18 ++- startup/GafferOSLUI/splineUIMetadata.py | 40 ------- startup/gui/menus.py | 3 + 9 files changed, 311 insertions(+), 41 deletions(-) create mode 100644 shaders/Pattern/ColorRamp.osl create mode 100644 shaders/Pattern/FloatRamp.osl delete mode 100644 startup/GafferOSLUI/splineUIMetadata.py diff --git a/Changes.md b/Changes.md index 996ab22b16..07edfc5598 100644 --- a/Changes.md +++ b/Changes.md @@ -22,6 +22,7 @@ Breaking Changes - SceneEditor : Removed `numInputs` argument to `Settings` constructor. - Gaffer::SplinePlug : - Removed support for loading splines saved with Gaffer version 0.40.0.0 and earlier +- OSL Shaders : Pattern/FloatSpline and Pattern/ColorSpline have been replaced by Pattern/FloatRamp and Pattern/ColorRamp. Old Gaffer scripts will automatically be updated on load, files exported from Gaffer will contain the new shaders. ( The .osl files for the old shaders are still included, so that old USD files can render ). 1.6.x.x (relative to 1.6.7.0) ======= diff --git a/python/GafferOSLTest/OSLShaderTest.py b/python/GafferOSLTest/OSLShaderTest.py index 91bad1b2a1..1d7da9db34 100644 --- a/python/GafferOSLTest/OSLShaderTest.py +++ b/python/GafferOSLTest/OSLShaderTest.py @@ -38,6 +38,7 @@ import pathlib import unittest import imath +import inspect import random import shutil @@ -1412,5 +1413,68 @@ def testStringArrayMetadata( self ) : self.assertEqual( node["parameters"]["size4Initialisers1"].defaultValue(), IECore.StringVectorData( [ "a", "", "", "" ] ) ) self.assertEqual( node["parameters"]["size4Initialisers4"].defaultValue(), IECore.StringVectorData( [ "a", "b", "c", "d" ] ) ) + def testDeprecatedSplineDeserialize( self ) : + + + + deprecatedSplineTemplate = inspect.cleandoc( """ + import Gaffer + import GafferOSL + import imath + + __children = {{}} + + __children["ColorSpline"] = GafferOSL.OSLShader( "ColorSpline" ) + parent.addChild( __children["ColorSpline"] ) + __children["ColorSpline"].loadShader( "Pattern/ColorSpline" ) + __children["ColorSpline"]["parameters"]["spline"].clearPoints() + __children["ColorSpline"]["parameters"]["spline"].addChild( Gaffer.ValuePlug( "p0", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) + __children["ColorSpline"]["parameters"]["spline"]["p0"].addChild( Gaffer.FloatPlug( "x", defaultValue = 0.0, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) + __children["ColorSpline"]["parameters"]["spline"]["p0"].addChild( Gaffer.Color3fPlug( "y", defaultValue = imath.Color3f( 0, 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) + __children["ColorSpline"]["parameters"]["spline"].addChild( Gaffer.ValuePlug( "p1", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) + __children["ColorSpline"]["parameters"]["spline"]["p1"].addChild( Gaffer.FloatPlug( "x", defaultValue = 1.0, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) + __children["ColorSpline"]["parameters"]["spline"]["p1"].addChild( Gaffer.Color3fPlug( "y", defaultValue = imath.Color3f( 1, 1, 1 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) + __children["ColorSpline"]["parameters"]["spline"].addChild( Gaffer.ValuePlug( "p2", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) + __children["ColorSpline"]["parameters"]["spline"]["p2"].addChild( Gaffer.FloatPlug( "x", defaultValue = 0.0, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) + __children["ColorSpline"]["parameters"]["spline"]["p2"].addChild( Gaffer.Color3fPlug( "y", defaultValue = imath.Color3f( 0, 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) + __children["ColorSpline"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) + __children["ColorSpline"]["parameters"]["spline"]["interpolation"].setValue( 2 ) + __children["ColorSpline"]["parameters"]["spline"]["p0"]["x"].setValue( 0.1 ) + __children["ColorSpline"]["parameters"]["spline"]["p0"]["y"].setValue( imath.Color3f( 0.1, 0.2, 0.3 ) ) + __children["ColorSpline"]["parameters"]["spline"]["p1"]["x"].setValue( 0.9 ) + __children["ColorSpline"]["parameters"]["spline"]["p1"]["y"].setValue( imath.Color3f( 0.7, 0.8, 0.9 ) ) + __children["ColorSpline"]["parameters"]["spline"]["p2"]["x"].setValue( 0.5 ) + __children["ColorSpline"]["parameters"]["spline"]["p2"]["y"].setValue( imath.Color3f( 0.3, 0.4, 0.5 ) ) + {} + __children["ColorSpline"]["__uiPosition"].setValue( imath.V2f( 17.8000011, -12.8500004 ) ) + + + del __children + """ ) + + for direction in [ "custom", "u", "v" ]: + if direction != "custom": + deprecatedSpline = deprecatedSplineTemplate.format( + '__children["ColorSpline"]["parameters"]["direction"].setValue("{}")'.format( direction ) + ) + else: + # In ColorSpline, the default value for "direction" was "custom", so there would be no + # explicit setValue + deprecatedSpline = deprecatedSplineTemplate.format( "" ) + + script = Gaffer.ScriptNode() + script.execute( deprecatedSpline ) + + self.assertEqual( script["ColorSpline"]["name"].getValue(), "Pattern/ColorRamp" ) + self.assertEqual( script["ColorSpline"]["parameters"]["direction"].getValue(), direction ) + + self.assertEqual( script["ColorSpline"]["parameters"]["ramp"]["interpolation"].getValue(), int( IECore.RampInterpolation.BSpline ) ) + self.assertAlmostEqual( script["ColorSpline"]["parameters"]["ramp"]["p0"]["x"].getValue(), 0.1 ) + self.assertEqual( script["ColorSpline"]["parameters"]["ramp"]["p0"]["y"].getValue(), imath.Color3f( 0.1, 0.2, 0.3 ) ) + self.assertAlmostEqual( script["ColorSpline"]["parameters"]["ramp"]["p1"]["x"].getValue(), 0.9 ) + self.assertEqual( script["ColorSpline"]["parameters"]["ramp"]["p1"]["y"].getValue(), imath.Color3f( 0.7, 0.8, 0.9 ) ) + self.assertAlmostEqual( script["ColorSpline"]["parameters"]["ramp"]["p2"]["x"].getValue(), 0.5 ) + self.assertEqual( script["ColorSpline"]["parameters"]["ramp"]["p2"]["y"].getValue(), imath.Color3f( 0.3, 0.4, 0.5 ) ) + if __name__ == "__main__": unittest.main() diff --git a/shaders/Pattern/ColorRamp.osl b/shaders/Pattern/ColorRamp.osl new file mode 100644 index 0000000000..377d94bab3 --- /dev/null +++ b/shaders/Pattern/ColorRamp.osl @@ -0,0 +1,112 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2016, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#include "GafferOSL/Spline.h" + +shader ColorRamp +( + + float rampPositions[] = { 0, 0, 1, 1 }, + color rampValues[] = { 0, 0, 1, 1 }, + string rampBasis = "catmull-rom", + + string direction = "v" [[ + string help = "Which direction the ramp is applied in. U or V use the UVs, Diagonal or Radial use the UVs together with a start and end position. Custom uses the `x` input, which may be hooked up to any shader returning a float. When using UVs, the overrideUV plug maybe be connected in order to use custom UVs.", + string widget = "popup", + string options = "Custom:custom|U:u|V:v|Diagonal:diagonal|Radial:radial", + int connectable = 0, + ]], + + float x = 0 [[ + string help = "The ramp coordinate to use when direction is set to Custom.", + string visibleExpression = "direction == \"custom\"", + ]], + point startPosition = 0 [[ + string help = "Determines the start of a Diagonal ramp, or the center of a Radial ramp.", + int gafferNoduleLayoutVisible = 0, + string visibleExpression = "direction == \"diagonal\" || direction == \"radial\"", + ]], + point endPosition = point( 1, 1, 0 ) [[ + string help = "Determines the end of a Diagonal ramp.", + int gafferNoduleLayoutVisible = 0, + string visibleExpression = "direction == \"diagonal\"", + ]], + float radius = 1 [[ + string help = "The size of the falloff in when direction is set to Radial.", + int gafferNoduleLayoutVisible = 0, + string visibleExpression = "direction == \"radial\"", + ]], + point overrideUV = 0 [[ + string help = "Connect to the nodule for this plug to override the UVs used when direction is set to U, V, Diagonal, or Radial. May be a 3 dimensional value for a 3 dimensional falloff.", + string widget = "null", + ]], + + output color c = 0 + +) +{ + point uv = point( u, v, 0 ); + if( isconnected( overrideUV ) ) + { + uv = overrideUV; + } + + float rampCoord; + if( direction == "custom" ) + { + rampCoord = x; + } + else if( direction == "u" ) + { + rampCoord = uv.x; + } + else if( direction == "v" ) + { + rampCoord = uv.y; + } + else if( direction == "diagonal" ) + { + vector disp = endPosition - startPosition; + rampCoord = dot( uv - startPosition, disp ) / dot( disp, disp ); + } + else if( direction == "radial" ) + { + vector disp = endPosition - startPosition; + rampCoord = length( uv - startPosition ) / radius; + } + + c = colorSpline( rampPositions, rampValues, rampBasis, rampCoord ); +} diff --git a/shaders/Pattern/ColorSpline.osl b/shaders/Pattern/ColorSpline.osl index 1ae28fcf40..a571799783 100644 --- a/shaders/Pattern/ColorSpline.osl +++ b/shaders/Pattern/ColorSpline.osl @@ -36,6 +36,7 @@ #include "GafferOSL/Spline.h" +// Now deprecated in favour of ColorRamp shader ColorSpline ( diff --git a/shaders/Pattern/FloatRamp.osl b/shaders/Pattern/FloatRamp.osl new file mode 100644 index 0000000000..dc6baa0257 --- /dev/null +++ b/shaders/Pattern/FloatRamp.osl @@ -0,0 +1,112 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2017, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#include "GafferOSL/Spline.h" + +shader FloatRamp +( + + float rampPositions[] = { 0, 0, 1, 1 }, + float rampValues[] = { 0, 0, 1, 1 }, + string rampBasis = "catmull-rom", + + string direction = "v" [[ + string help = "Which direction the ramp is applied in. U or V use the UVs, Diagonal or Radial use the UVs together with a start and end position. Custom uses the `x` input, which may be hooked up to any shader returning a float. When using UVs, the overrideUV plug maybe be connected in order to use custom UVs.", + string widget = "popup", + string options = "Custom:custom|U:u|V:v|Diagonal:diagonal|Radial:radial", + int connectable = 0, + ]], + + float x = 0 [[ + string help = "The ramp coordinate to use when direction is set to Custom.", + string visibleExpression = "direction == \"custom\"", + ]], + point startPosition = 0 [[ + string help = "Determines the start of a Diagonal ramp, or the center of a Radial ramp.", + int gafferNoduleLayoutVisible = 0, + string visibleExpression = "direction == \"diagonal\" || direction == \"radial\"", + ]], + point endPosition = point( 1, 1, 0 ) [[ + string help = "Determines the end of a Diagonal ramp.", + int gafferNoduleLayoutVisible = 0, + string visibleExpression = "direction == \"diagonal\"", + ]], + float radius = 1 [[ + string help = "The size of the falloff in when direction is set to Radial.", + int gafferNoduleLayoutVisible = 0, + string visibleExpression = "direction == \"radial\"", + ]], + point overrideUV = 0 [[ + string help = "Connect to the nodule for this plug to override the UVs used when direction is set to U, V, Diagonal, or Radial. May be a 3 dimensional value for a 3 dimensional falloff.", + string widget = "null", + ]], + + output color c = 0 + +) +{ + point uv = point( u, v, 0 ); + if( isconnected( overrideUV ) ) + { + uv = overrideUV; + } + + float rampCoord; + if( direction == "custom" ) + { + rampCoord = x; + } + else if( direction == "u" ) + { + rampCoord = uv.x; + } + else if( direction == "v" ) + { + rampCoord = uv.y; + } + else if( direction == "diagonal" ) + { + vector disp = endPosition - startPosition; + rampCoord = dot( uv - startPosition, disp ) / dot( disp, disp ); + } + else if( direction == "radial" ) + { + vector disp = endPosition - startPosition; + rampCoord = length( uv - startPosition ) / radius; + } + + c = floatSpline( rampPositions, rampValues, rampBasis, rampCoord ); +} diff --git a/shaders/Pattern/FloatSpline.osl b/shaders/Pattern/FloatSpline.osl index f52b1fa982..6e18ef0864 100644 --- a/shaders/Pattern/FloatSpline.osl +++ b/shaders/Pattern/FloatSpline.osl @@ -36,6 +36,7 @@ #include "GafferOSL/Spline.h" +// Now deprecated in favour of FloatRamp shader FloatSpline ( diff --git a/startup/GafferOSL/shaderNameCompatibility.py b/startup/GafferOSL/shaderNameCompatibility.py index d28b2147c2..0b430b7d15 100644 --- a/startup/GafferOSL/shaderNameCompatibility.py +++ b/startup/GafferOSL/shaderNameCompatibility.py @@ -34,6 +34,7 @@ # ########################################################################## +import Gaffer import GafferOSL __nameMapping = { @@ -48,6 +49,8 @@ "Maths/FloatMultiply" : "Maths/MultiplyFloat", "Maths/VectorAdd" : "Maths/AddVector", "Maths/VectorMultiply" : "Maths/ScaleVector", + "Pattern/FloatSpline" : "Pattern/FloatRamp", + "Pattern/ColorSpline" : "Pattern/ColorRamp", # A whole bunch of MaterialX shaders were renamed from `mx__` # to `mx___` here : # @@ -149,8 +152,21 @@ def __loadShaderWrapper( originalLoadShader ) : def loadRenamedShader( self, shaderName, **kwargs ) : renamed = __nameMapping.get( shaderName, shaderName ) - return originalLoadShader( self, renamed, **kwargs ) + result = originalLoadShader( self, renamed, **kwargs ) + if shaderName in [ "Pattern/FloatSpline", "Pattern/ColorSpline" ]: + self["parameters"]["direction"].setValue( "custom" ) + return result return loadRenamedShader GafferOSL.OSLShader.loadShader = __loadShaderWrapper( GafferOSL.OSLShader.loadShader ) + + +def __splineAliasForRamps( plug ) : + + if plug.node()["name"].getValue() in [ "Pattern/ColorRamp", "Pattern/FloatRamp" ]: + return "ramp" + + return None + +Gaffer.Metadata.registerValue( GafferOSL.OSLShader, "parameters", "compatibility:childAlias:spline", __splineAliasForRamps ) diff --git a/startup/GafferOSLUI/splineUIMetadata.py b/startup/GafferOSLUI/splineUIMetadata.py deleted file mode 100644 index 55aed82fed..0000000000 --- a/startup/GafferOSLUI/splineUIMetadata.py +++ /dev/null @@ -1,40 +0,0 @@ -########################################################################## -# -# Copyright (c) 2023, Image Engine Design Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above -# copyright notice, this list of conditions and the following -# disclaimer. -# -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided with -# the distribution. -# -# * Neither the name of John Haddon nor the names of -# any other contributors to this software may be used to endorse or -# promote products derived from this software without specific prior -# written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -########################################################################## - -import Gaffer - -Gaffer.Metadata.registerValue( "osl:shader:Pattern/ColorSpline:direction", "userDefault", "v" ) -Gaffer.Metadata.registerValue( "osl:shader:Pattern/FloatSpline:direction", "userDefault", "v" ) diff --git a/startup/gui/menus.py b/startup/gui/menus.py index 6d9453bcd3..9a8048d00a 100644 --- a/startup/gui/menus.py +++ b/startup/gui/menus.py @@ -111,6 +111,9 @@ def addHelpMenuItems( items ) : GafferSceneUI.ShaderUI.hideShaders( IECore.PathMatcher( [ ".../__*" ] ) ) +# Hide deprecated shaders +GafferSceneUI.ShaderUI.hideShaders( IECore.PathMatcher( [ "Pattern/ColorSpline.oso", "Pattern/FloatSpline.oso" ] ) ) + # Arnold nodes if moduleSearchPath.find( "arnold" ) : From 6cc90d30d5645cf901fa90741e8ef6e875f72ae2 Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 28 Oct 2025 16:39:45 -0700 Subject: [PATCH 10/11] Use IECore::Ramp, and rename all "splines" that are now "ramps" --- Changes.md | 2 + include/Gaffer/RampPlug.h | 127 ++++ include/Gaffer/SplinePlug.h | 210 ------ include/Gaffer/TypeIds.h | 6 +- .../IECoreCyclesPreview/SocketAlgo.h | 8 +- include/GafferImage/Ramp.h | 6 +- include/GafferScene/AttributeVisualiser.h | 6 +- include/GafferUI/PathColumn.h | 2 +- python/Gaffer/ExtensionAlgo.py | 2 +- python/GafferDispatch/Wedge.py | 8 +- python/GafferImageTest/SamplerTest.py | 2 +- python/GafferOSLTest/OSLCodeTest.py | 12 +- .../GafferOSLTest/OSLExpressionEngineTest.py | 2 +- python/GafferOSLTest/OSLImageTest.py | 110 ++-- python/GafferOSLTest/OSLShaderTest.py | 120 ++-- python/GafferOSLTest/ShadingEngineTest.py | 13 +- .../shaders/PxrSplineParameters.osl | 2 +- python/GafferOSLUI/OSLCodeUI.py | 18 +- python/GafferOSLUI/OSLShaderUI.py | 2 +- python/GafferOSLUITest/OSLShaderUITest.py | 20 +- .../RenderManShaderTest.py | 13 +- python/GafferSceneTest/ImageScatterTest.py | 4 +- python/GafferSceneTest/ImageToPointsTest.py | 8 +- python/GafferSceneTest/ShaderTest.py | 58 +- python/GafferSceneUI/AttributeVisualiserUI.py | 4 +- python/GafferSceneUI/CameraQueryUI.py | 4 +- python/GafferTest/CollectTest.py | 2 +- python/GafferTest/ExpressionTest.py | 6 +- python/GafferTest/ExtensionAlgoTest.py | 2 +- python/GafferTest/PlugAlgoTest.py | 8 +- .../{SplinePlugTest.py => RampPlugTest.py} | 216 +++---- python/GafferTest/ReferenceTest.py | 100 +-- python/GafferTest/TestCase.py | 2 +- python/GafferTest/__init__.py | 2 +- python/GafferUI/ColorSwatchPlugValueWidget.py | 2 +- python/GafferUI/RampPlugValueWidget.py | 138 +++- .../{SplineWidget.py => RampWidget.py} | 42 +- python/GafferUI/SplinePlugValueWidget.py | 147 ----- python/GafferUI/_StyleSheet.py | 4 +- python/GafferUI/__init__.py | 3 +- python/IECoreArnoldTest/CameraAlgoTest.py | 10 +- python/IECoreArnoldTest/RendererTest.py | 173 ++--- python/IECoreDelightTest/RendererTest.py | 70 +- src/Gaffer/Plug.cpp | 2 +- src/Gaffer/PlugAlgo.cpp | 12 +- src/Gaffer/RampPlug.cpp | 357 +++++++++++ src/Gaffer/Reference.cpp | 30 +- src/Gaffer/SplinePlug.cpp | 596 ------------------ src/Gaffer/ValuePlug.cpp | 2 +- src/GafferBindings/ValuePlugBinding.cpp | 2 +- .../IECoreCyclesPreview/ShaderNetworkAlgo.cpp | 14 +- .../IECoreCyclesPreview/SocketAlgo.cpp | 22 +- src/GafferCycles/SocketHandler.cpp | 22 +- src/GafferImage/Ramp.cpp | 18 +- src/GafferModule/GafferModule.cpp | 4 +- ...inePlugBinding.cpp => RampPlugBinding.cpp} | 105 +-- ...{SplinePlugBinding.h => RampPlugBinding.h} | 2 +- src/GafferOSL/OSLCode.cpp | 8 +- src/GafferOSL/OSLShader.cpp | 176 +++--- src/GafferRenderMan/RenderManShader.cpp | 96 +-- src/GafferScene/AttributeVisualiser.cpp | 20 +- src/GafferScene/Shader.cpp | 86 +-- src/GafferSceneTest/TestShader.cpp | 4 +- .../PathListingWidgetBinding.cpp | 31 +- src/IECoreArnold/CameraAlgo.cpp | 22 +- src/IECoreArnold/ShaderNetworkAlgo.cpp | 2 +- src/IECoreDelight/ShaderNetworkAlgo.cpp | 13 +- startup/Gaffer/splinePlugCompatibility.py | 59 ++ startup/GafferArnold/cameraParameters.py | 2 +- startup/GafferArnoldUI/cameraTweaks.py | 6 +- 70 files changed, 1445 insertions(+), 1964 deletions(-) create mode 100644 include/Gaffer/RampPlug.h delete mode 100644 include/Gaffer/SplinePlug.h rename python/GafferTest/{SplinePlugTest.py => RampPlugTest.py} (66%) rename python/GafferUI/{SplineWidget.py => RampWidget.py} (90%) delete mode 100644 python/GafferUI/SplinePlugValueWidget.py create mode 100644 src/Gaffer/RampPlug.cpp delete mode 100644 src/Gaffer/SplinePlug.cpp rename src/GafferModule/{SplinePlugBinding.cpp => RampPlugBinding.cpp} (62%) rename src/GafferModule/{SplinePlugBinding.h => RampPlugBinding.h} (98%) create mode 100644 startup/Gaffer/splinePlugCompatibility.py diff --git a/Changes.md b/Changes.md index 07edfc5598..5483821095 100644 --- a/Changes.md +++ b/Changes.md @@ -22,7 +22,9 @@ Breaking Changes - SceneEditor : Removed `numInputs` argument to `Settings` constructor. - Gaffer::SplinePlug : - Removed support for loading splines saved with Gaffer version 0.40.0.0 and earlier + - Renamed to Gaffer::RampPlug. Removed SplineDefinition ( use IECore::Ramp instead ). - OSL Shaders : Pattern/FloatSpline and Pattern/ColorSpline have been replaced by Pattern/FloatRamp and Pattern/ColorRamp. Old Gaffer scripts will automatically be updated on load, files exported from Gaffer will contain the new shaders. ( The .osl files for the old shaders are still included, so that old USD files can render ). +- GafferUI : Renamed SplineWidget to RampWidget. Renamed SplinePlugValueWidget to RampPlugValueWidget. The old RampPlugValueWidget is no longer exposed, since it was only used internally. 1.6.x.x (relative to 1.6.7.0) ======= diff --git a/include/Gaffer/RampPlug.h b/include/Gaffer/RampPlug.h new file mode 100644 index 0000000000..4560bf8ed0 --- /dev/null +++ b/include/Gaffer/RampPlug.h @@ -0,0 +1,127 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011-2012, John Haddon. All rights reserved. +// Copyright (c) 2013, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "Gaffer/NumericPlug.h" +#include "Gaffer/PlugType.h" +#include "Gaffer/TypedPlug.h" + +#include "IECore/Ramp.h" + +namespace Gaffer +{ + +/// The RampPlug allows the user to manipulate an IECore::Ramp, which is +/// a simple curve representation with a list of control points and an +/// interpolation. +// +/// Rather than storing the value atomically, the +/// points and interpolation are represented as individual plugs, +/// allowing the positions of individual points to have input +/// connections from other nodes. + +template +class GAFFER_API RampPlug : public ValuePlug +{ + + public : + + using ValueType = T; + using XPlugType = typename PlugType::Type; + using YPlugType = typename PlugType::Type; + + GAFFER_PLUG_DECLARE_TEMPLATE_TYPE( RampPlug, ValuePlug ); + + explicit RampPlug( + const std::string &name = defaultName(), + Direction direction=In, + const T &defaultValue = T(), + unsigned flags = Default + ); + ~RampPlug() override; + + /// Implemented to only accept children which are suitable for use as points + /// in the ramp. + bool acceptsChild( const GraphComponent *potentialChild ) const override; + PlugPtr createCounterpart( const std::string &name, Direction direction ) const override; + + const T &defaultValue() const; + void setToDefault() override; + bool isSetToDefault() const override; + void resetDefault() override; + IECore::MurmurHash defaultHash() const override; + + /// Sets the value of the points and interpolation child plugs + /// \undoable + void setValue( const T &value ); + /// Matching to setValue + T getValue() const; + + IntPlug *interpolationPlug(); + const IntPlug *interpolationPlug() const; + + /// Returns the number of point plugs + unsigned numPoints() const; + /// \undoable + unsigned addPoint(); + /// \undoable + void removePoint( unsigned pointIndex ); + /// \undoable + void clearPoints(); + + ValuePlug *pointPlug( unsigned pointIndex ); + const ValuePlug *pointPlug( unsigned pointIndex ) const; + XPlugType *pointXPlug( unsigned pointIndex ); + const XPlugType *pointXPlug( unsigned pointIndex ) const; + YPlugType *pointYPlug( unsigned pointIndex ); + const YPlugType *pointYPlug( unsigned pointIndex ) const; + + private : + + T m_defaultValue; +}; + +using RampffPlug = RampPlug; +using RampfColor3fPlug = RampPlug; +using RampfColor4fPlug = RampPlug; + +IE_CORE_DECLAREPTR( RampffPlug ); +IE_CORE_DECLAREPTR( RampfColor3fPlug ); +IE_CORE_DECLAREPTR( RampfColor4fPlug ); + +} // namespace Gaffer diff --git a/include/Gaffer/SplinePlug.h b/include/Gaffer/SplinePlug.h deleted file mode 100644 index 3bf7f530b6..0000000000 --- a/include/Gaffer/SplinePlug.h +++ /dev/null @@ -1,210 +0,0 @@ -////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) 2011-2012, John Haddon. All rights reserved. -// Copyright (c) 2013, Image Engine Design Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above -// copyright notice, this list of conditions and the following -// disclaimer. -// -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided with -// the distribution. -// -// * Neither the name of John Haddon nor the names of -// any other contributors to this software may be used to endorse or -// promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -////////////////////////////////////////////////////////////////////////// - -#pragma once - -#include "Gaffer/NumericPlug.h" -#include "Gaffer/PlugType.h" -#include "Gaffer/TypedPlug.h" - -#include "IECore/Spline.h" - -namespace Gaffer -{ - -// This lives outside the class because we don't want multiple incompatible templated versions of -// the same enum floating around -enum SplineDefinitionInterpolation -{ - SplineDefinitionInterpolationLinear, - SplineDefinitionInterpolationCatmullRom, - SplineDefinitionInterpolationBSpline, - SplineDefinitionInterpolationMonotoneCubic, - SplineDefinitionInterpolationConstant, -}; - -// Represents a spline in a way closely aligned with how a user interacts with a spline in the UI. -// The significant differences from IECore::Spline are that end points are not duplicated, and the -// MonotoneCubic interpolation is supported. -// -// This class takes care of converting to IECore::Spline, and helps with converting back from it. -// -// In the future, we aim to move this to Cortex, and use it for all setup of splines, and replace -// IECore::Spline with IECore::SplineEvaluator, which would store things in the right -// format for fast evaluation, but would be totally opaque otherwise - the only way to set up an -// evaluator would be using setting up a SplineDefinition and calling SplineDefinition::evaluator(). - -template -struct GAFFER_API SplineDefinition -{ - using XType = typename T::XType; - using YType = typename T::YType; - using PointContainer = typename T::PointContainer; - using Point = typename PointContainer::value_type; - - SplineDefinition() : interpolation( SplineDefinitionInterpolationCatmullRom ) - { - } - - SplineDefinition( const PointContainer &p, SplineDefinitionInterpolation i ) - : points( p ), interpolation( i ) - { - } - - PointContainer points; - SplineDefinitionInterpolation interpolation; - - - // Convert to Cortex Spline - // In the future, IECore::Spline may be replaced with IECore::SplineEvaluator, and this - // function would be the only way to setup one. - T spline() const; - - // Removes start and end points with duplicated X values. - // - // Sources of spline data may or may not contain duplicated end points for a variety of reasons - // ( such as IECore::Splineff having duplicated end points so that spline evaluation will reach - // the final value, or OSL have duplicated end points even for constant and linear splines ). - // - // The spline UI's that Gaffer uses to interact with splines don't support duplicated end - // points well, so regardless of why they are there, this function will remove them. - bool trimEndPoints(); - - bool operator==( const SplineDefinition &rhs ) const - { - return interpolation == rhs.interpolation && points == rhs.points; - } - - bool operator!=( const SplineDefinition &rhs ) const - { - return interpolation != rhs.interpolation || points != rhs.points; - } - -private: - int endPointMultiplicity() const; -}; - -/// The SplinePlug allows the user to manipulate splines that can be -/// converted to IECore::Splines. It's value is a very simple and easy to edit -/// spline representation named SplineDefinition - just a list of control points -/// with one of the interpolations above. -// -/// Rather than storing the value atomically, the -/// points and interpolation are represented as individual plugs, -/// allowing the positions of individual points to have input -/// connections from other nodes. -/// -/// The value stored should be a clean, user editable value. Underlying technical -/// details such as adding repeated endpoint values are added when converting to -/// IECore::Spline. -template -class GAFFER_API SplinePlug : public ValuePlug -{ - - public : - - using ValueType = T; - using XPlugType = typename PlugType::Type; - using YPlugType = typename PlugType::Type; - - GAFFER_PLUG_DECLARE_TEMPLATE_TYPE( SplinePlug, ValuePlug ); - - explicit SplinePlug( - const std::string &name = defaultName(), - Direction direction=In, - const T &defaultValue = T(), - unsigned flags = Default - ); - ~SplinePlug() override; - - /// Implemented to only accept children which are suitable for use as points - /// in the spline. - bool acceptsChild( const GraphComponent *potentialChild ) const override; - PlugPtr createCounterpart( const std::string &name, Direction direction ) const override; - - const T &defaultValue() const; - void setToDefault() override; - bool isSetToDefault() const override; - void resetDefault() override; - IECore::MurmurHash defaultHash() const override; - - /// Sets the value of the points and interpolation child plugs - /// \undoable - void setValue( const T &value ); - /// Matching to setValue - T getValue() const; - - IntPlug *interpolationPlug(); - const IntPlug *interpolationPlug() const; - - /// Returns the number of point plugs - note that - /// because duplicate endpoints are not stored directly as - /// plugs, this may differ from the number of points - /// in the spline passed to setValue(). - unsigned numPoints() const; - /// \undoable - unsigned addPoint(); - /// \undoable - void removePoint( unsigned pointIndex ); - /// \undoable - void clearPoints(); - - ValuePlug *pointPlug( unsigned pointIndex ); - const ValuePlug *pointPlug( unsigned pointIndex ) const; - XPlugType *pointXPlug( unsigned pointIndex ); - const XPlugType *pointXPlug( unsigned pointIndex ) const; - YPlugType *pointYPlug( unsigned pointIndex ); - const YPlugType *pointYPlug( unsigned pointIndex ) const; - - private : - - T m_defaultValue; -}; - -using SplineDefinitionff = SplineDefinition; -using SplineDefinitionfColor3f = SplineDefinition; -using SplineDefinitionfColor4f = SplineDefinition; - -using SplineffPlug = SplinePlug; -using SplinefColor3fPlug = SplinePlug; -using SplinefColor4fPlug = SplinePlug; - -IE_CORE_DECLAREPTR( SplineffPlug ); -IE_CORE_DECLAREPTR( SplinefColor3fPlug ); -IE_CORE_DECLAREPTR( SplinefColor4fPlug ); - -} // namespace Gaffer diff --git a/include/Gaffer/TypeIds.h b/include/Gaffer/TypeIds.h index afeab8892e..52d9daf6cd 100644 --- a/include/Gaffer/TypeIds.h +++ b/include/Gaffer/TypeIds.h @@ -62,8 +62,8 @@ enum TypeId V3iPlugTypeId = 118016, Color3fPlugTypeId = 118017, Color4fPlugTypeId = 118018, - SplineffPlugTypeId = 118019, - SplinefColor3fPlugTypeId = 118020, + RampffPlugTypeId = 118019, + RampfColor3fPlugTypeId = 118020, M33fPlugTypeId = 118021, M44fPlugTypeId = 118022, BoolPlugTypeId = 118023, @@ -98,7 +98,7 @@ enum TypeId AtomicCompoundDataPlugTypeId = 118052, BoxTypeId = 118053, InternedStringVectorDataPlugTypeId = 118054, - SplinefColor4fPlugTypeId = 118055, + RampfColor4fPlugTypeId = 118055, NumericBookmarkSetTypeId = 118056, NameSwitchTypeId = 118057, Transform2DPlugTypeId = 118058, diff --git a/include/GafferCycles/IECoreCyclesPreview/SocketAlgo.h b/include/GafferCycles/IECoreCyclesPreview/SocketAlgo.h index f06e082d39..25b33104df 100644 --- a/include/GafferCycles/IECoreCyclesPreview/SocketAlgo.h +++ b/include/GafferCycles/IECoreCyclesPreview/SocketAlgo.h @@ -39,7 +39,7 @@ #include "IECore/Export.h" #include "IECore/CompoundData.h" -#include "IECore/Spline.h" +#include "IECore/Ramp.h" // Cycles IECORE_PUSH_DEFAULT_VISIBILITY @@ -74,9 +74,9 @@ IECORECYCLES_API Imath::M44f getTransform( const ccl::Transform transform ); IECORECYCLES_API void setSocket( ccl::Node *node, const ccl::SocketType *socket, const IECore::Data *value ); IECORECYCLES_API void setSocket( ccl::Node *node, const std::string &name, const IECore::Data *value ); -// Splines -IECORECYCLES_API void setRampSocket( ccl::Node *node, const ccl::SocketType *socket, const IECore::Splineff &spline ); -IECORECYCLES_API void setRampSocket( ccl::Node *node, const ccl::SocketType *socket, const IECore::SplinefColor3f &spline ); +// Ramps +IECORECYCLES_API void setRampSocket( ccl::Node *node, const ccl::SocketType *socket, const IECore::Rampff &ramp ); +IECORECYCLES_API void setRampSocket( ccl::Node *node, const ccl::SocketType *socket, const IECore::RampfColor3f &ramp ); // ParamValue IECORECYCLES_API ccl::ParamValue setParamValue( const IECore::InternedString &name, const IECore::Data *value ); diff --git a/include/GafferImage/Ramp.h b/include/GafferImage/Ramp.h index df9841a056..9492ce9390 100644 --- a/include/GafferImage/Ramp.h +++ b/include/GafferImage/Ramp.h @@ -40,7 +40,7 @@ #include "GafferImage/FormatPlug.h" #include "Gaffer/CompoundNumericPlug.h" -#include "Gaffer/SplinePlug.h" +#include "Gaffer/RampPlug.h" #include "Gaffer/StringPlug.h" namespace Gaffer @@ -66,8 +66,8 @@ class GAFFERIMAGE_API Ramp : public FlatImageSource GafferImage::FormatPlug *formatPlug(); const GafferImage::FormatPlug *formatPlug() const; - Gaffer::SplinefColor4fPlug *rampPlug(); - const Gaffer::SplinefColor4fPlug *rampPlug() const; + Gaffer::RampfColor4fPlug *rampPlug(); + const Gaffer::RampfColor4fPlug *rampPlug() const; Gaffer::V2fPlug *startPositionPlug(); const Gaffer::V2fPlug *startPositionPlug() const; diff --git a/include/GafferScene/AttributeVisualiser.h b/include/GafferScene/AttributeVisualiser.h index 9ec596d83a..4c8f20804d 100644 --- a/include/GafferScene/AttributeVisualiser.h +++ b/include/GafferScene/AttributeVisualiser.h @@ -39,7 +39,7 @@ #include "GafferScene/AttributeProcessor.h" #include "Gaffer/NumericPlug.h" -#include "Gaffer/SplinePlug.h" +#include "Gaffer/RampPlug.h" namespace Gaffer { @@ -81,8 +81,8 @@ class GAFFERSCENE_API AttributeVisualiser : public AttributeProcessor Gaffer::FloatPlug *maxPlug(); const Gaffer::FloatPlug *maxPlug() const; - Gaffer::SplinefColor3fPlug *rampPlug(); - const Gaffer::SplinefColor3fPlug *rampPlug() const; + Gaffer::RampfColor3fPlug *rampPlug(); + const Gaffer::RampfColor3fPlug *rampPlug() const; Gaffer::StringPlug *shaderTypePlug(); const Gaffer::StringPlug *shaderTypePlug() const; diff --git a/include/GafferUI/PathColumn.h b/include/GafferUI/PathColumn.h index 09dd858d6d..542249590e 100644 --- a/include/GafferUI/PathColumn.h +++ b/include/GafferUI/PathColumn.h @@ -110,7 +110,7 @@ class GAFFERUI_API PathColumn : public IECore::RefCounted, public Gaffer::Signal /// - FloatData, DoubleData /// - DateTimeData /// - V2fData, V3fData, Color3fData, Color4fData - /// - SplineffData, SplinefColor3fData + /// - RampffData, RampfColor3fData IECore::ConstDataPtr value; /// An additional icon to be displayed next to the primary /// value. Supported types : diff --git a/python/Gaffer/ExtensionAlgo.py b/python/Gaffer/ExtensionAlgo.py index b7d70dd368..a54af7bf8a 100644 --- a/python/Gaffer/ExtensionAlgo.py +++ b/python/Gaffer/ExtensionAlgo.py @@ -141,7 +141,7 @@ def __removeDynamicFlags( self ) : for plug in Gaffer.Plug.Range( self ) : plug.setFlags( Gaffer.Plug.Flags.Dynamic, False ) - if not isinstance( plug, ( Gaffer.SplineffPlug, Gaffer.SplinefColor3fPlug, Gaffer.SplinefColor4fPlug ) ) : + if not isinstance( plug, ( Gaffer.RampffPlug, Gaffer.RampfColor3fPlug, Gaffer.RampfColor4fPlug ) ) : for plug in Gaffer.Plug.RecursiveRange( plug ) : plug.setFlags( Gaffer.Plug.Flags.Dynamic, False ) diff --git a/python/GafferDispatch/Wedge.py b/python/GafferDispatch/Wedge.py index 75217f5e54..150b939c0c 100644 --- a/python/GafferDispatch/Wedge.py +++ b/python/GafferDispatch/Wedge.py @@ -73,13 +73,13 @@ def __init__( self, name = "Wedge" ) : # color range - self["ramp"] = Gaffer.SplinefColor3fPlug( - defaultValue = Gaffer.SplineDefinitionfColor3f( + self["ramp"] = Gaffer.RampfColor3fPlug( + defaultValue = IECore.RampfColor3f( ( ( 0, imath.Color3f( 0 ) ), ( 1, imath.Color3f( 1 ) ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) ) @@ -128,7 +128,7 @@ def values( self ) : elif mode == self.Mode.ColorRange : - spline = self["ramp"].getValue().spline() + spline = self["ramp"].getValue().evaluator() steps = self["colorSteps"].getValue() values = [ spline( i / float( steps - 1 ) ) for i in range( 0, steps ) ] diff --git a/python/GafferImageTest/SamplerTest.py b/python/GafferImageTest/SamplerTest.py index 8577cdc9b4..194aef2c36 100644 --- a/python/GafferImageTest/SamplerTest.py +++ b/python/GafferImageTest/SamplerTest.py @@ -259,7 +259,7 @@ def testVisitPixels( self ): ramp["format"].setValue( GafferImage.Format( width, height, 1.000 ) ) rampScale = ( width * height - 1 ) / ( width * width + 1 ) ramp["endPosition"].setValue( imath.V2f( 0.5 + 1 * rampScale, 0.5 + width * rampScale ) ) - ramp['ramp'].setValue( Gaffer.SplineDefinitionfColor4f( ( ( 0, imath.Color4f( 0 ) ), ( 1, imath.Color4f( width * height - 1 ) )), Gaffer.SplineDefinitionInterpolation.Linear ) ) + ramp['ramp'].setValue( IECore.RampfColor4f( ( ( 0, imath.Color4f( 0 ) ), ( 1, imath.Color4f( width * height - 1 ) )), IECore.RampInterpolation.Linear ) ) center = imath.V2i( width // 2, height // 2 ) diff --git a/python/GafferOSLTest/OSLCodeTest.py b/python/GafferOSLTest/OSLCodeTest.py index 5191a1e0d4..273b212f1f 100644 --- a/python/GafferOSLTest/OSLCodeTest.py +++ b/python/GafferOSLTest/OSLCodeTest.py @@ -179,18 +179,16 @@ def testImageProcessingFunctions( self ) : oslCode["out"]["out"] = Gaffer.FloatPlug( direction = Gaffer.Plug.Direction.Out, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) self.__assertNoError( oslCode, oslCode["code"].setValue, 'out = inChannel( "R", 0 );' ) - def testColorSpline( self ) : + def testColorRamp( self ) : oslCode = GafferOSL.OSLCode() - oslCode["parameters"]["sp"] = Gaffer.SplinefColor3fPlug( - defaultValue = IECore.SplinefColor3f( - IECore.CubicBasisf.catmullRom(), + oslCode["parameters"]["sp"] = Gaffer.RampfColor3fPlug( + defaultValue = IECore.RampfColor3f( ( ( 0, imath.Color3f( 0 ) ), - ( 0, imath.Color3f( 0 ) ), - ( 1, imath.Color3f( 1 ) ), ( 1, imath.Color3f( 1 ) ), - ) + ), + IECore.RampInterpolation.CatmullRom ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) diff --git a/python/GafferOSLTest/OSLExpressionEngineTest.py b/python/GafferOSLTest/OSLExpressionEngineTest.py index 870496976e..d7cd311acc 100644 --- a/python/GafferOSLTest/OSLExpressionEngineTest.py +++ b/python/GafferOSLTest/OSLExpressionEngineTest.py @@ -454,7 +454,7 @@ def testIdentifier( self ) : s["n"] = Gaffer.Node() s["n"]["user"]["i"] = Gaffer.FloatPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) s["n"]["user"]["o"] = Gaffer.FloatPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - s["n"]["user"]["s"] = Gaffer.SplineffPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + s["n"]["user"]["s"] = Gaffer.RampffPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) s["e"] = Gaffer.Expression() s["e"].setExpression( "", "OSL" ) diff --git a/python/GafferOSLTest/OSLImageTest.py b/python/GafferOSLTest/OSLImageTest.py index 08d54ed24e..af842fbb5e 100644 --- a/python/GafferOSLTest/OSLImageTest.py +++ b/python/GafferOSLTest/OSLImageTest.py @@ -858,9 +858,10 @@ def testOSLSplineMatch( self ): g = GafferOSL.OSLShader() g.loadShader( "Utility/Globals" ) - colorSpline = GafferOSL.OSLShader() - colorSpline.loadShader( "Pattern/ColorSpline" ) - colorSpline["parameters"]["x"].setInput( g["out"]["globalU"] ) + colorRamp = GafferOSL.OSLShader() + colorRamp.loadShader( "Pattern/ColorRamp" ) + colorRamp["parameters"]["direction"].setValue( "custom" ) + colorRamp["parameters"]["x"].setInput( g["out"]["globalU"] ) # Values chosen to trigger a precision issue with OSL's splineinverse on a constant basis # if it is not avoided. The values have also been selected a little to avoid showing @@ -871,8 +872,8 @@ def testOSLSplineMatch( self ): # * The values are chosen so that the discontinuities in "constant" mode don't lie # directly on a pixel center - if they did, it's comes down solely to floating point # precision which side we lie on. - colorSpline["parameters"]["spline"].setValue( - Gaffer.SplineDefinitionfColor3f( + colorRamp["parameters"]["ramp"].setValue( + IECore.RampfColor3f( ( ( 0.1580, imath.Color3f( 0.71, 0.21, 0.39 ) ), ( 0.2249, imath.Color3f( 0, 0.30, 0 ) ), @@ -884,28 +885,29 @@ def testOSLSplineMatch( self ): ( 0.4607, imath.Color3f( 0.71, 0.21, 0.39 ) ), ( 0.5996, imath.Color3f( 0, 1, 1 ) ), ( 0.9235, imath.Color3f( 1, 0.25, 0.25 ) ) - ), Gaffer.SplineDefinitionInterpolation.Constant + ), IECore.RampInterpolation.Constant ) ) oslImage = GafferOSL.OSLImage( "OSLImage" ) oslImage["channels"].addChild( Gaffer.NameValuePlug( "", Gaffer.Color3fPlug( "value" ), True, "channel" ) ) - oslImage["channels"]["channel"]["value"].setInput( colorSpline["out"]["c"] ) + oslImage["channels"]["channel"]["value"].setInput( colorRamp["out"]["c"] ) oslImage["defaultFormat"].setValue( GafferImage.Format( 3000, 64, 1.000 ) ) - for i in Gaffer.SplineDefinitionInterpolation.names.values(): - colorSpline["parameters"]["spline"]["interpolation"].setValue( i ) - cortexSpline = colorSpline["parameters"]["spline"].getValue().spline() - samplers = [ - GafferImage.Sampler( oslImage["out"], c, imath.Box2i( imath.V2i( 0 ), imath.V2i( 3000, 1 ) ) ) - for c in [ "R", "G", "B" ] - ] - for x in range( 3000 ): - result = cortexSpline( ( x + 0.5 ) / 3000.0 ) - for c in range(3): - self.assertAlmostEqual( samplers[c].sample( x, 0 ), result[c], places = 3 ) + for i in IECore.RampInterpolation.names.values(): + with self.subTest( interpolation = i ): + colorRamp["parameters"]["ramp"]["interpolation"].setValue( i ) + cortexRamp = colorRamp["parameters"]["ramp"].getValue().evaluator() + samplers = [ + GafferImage.Sampler( oslImage["out"], c, imath.Box2i( imath.V2i( 0 ), imath.V2i( 3000, 1 ) ) ) + for c in [ "R", "G", "B" ] + ] + for x in range( 3000 ): + result = cortexRamp( ( x + 0.5 ) / 3000.0 ) + for c in range(3): + self.assertAlmostEqual( samplers[c].sample( x, 0 ), result[c], places = 3 ) - def testOSLSplineConnections( self ): + def testOSLRampConnections( self ): g = GafferOSL.OSLShader() g.loadShader( "Utility/Globals" ) @@ -915,17 +917,17 @@ def testOSLSplineConnections( self ): invertU["parameters"]["a"].setValue( 1.0 ) invertU["parameters"]["b"].setInput( g["out"]["globalU"] ) - floatSpline = GafferOSL.OSLShader() - floatSpline.loadShader( "Pattern/FloatSpline" ) - floatSpline["parameters"]["x"].setInput( g["out"]["globalV"] ) - floatSpline['parameters']['spline'].setValue( Gaffer.SplineDefinitionff( ( ( 1/8, 0 ), ( 3/8, 0 ), ( 5/8, 1 ), ( 7/8, 1 )), Gaffer.SplineDefinitionInterpolation.Constant ) ) - floatSpline["parameters"]["spline"]["p1"]["y"].setInput( invertU["out"]["out"] ) - floatSpline["parameters"]["spline"]["p2"]["y"].setInput( g["out"]["globalU"] ) + floatRamp = GafferOSL.OSLShader() + floatRamp.loadShader( "Pattern/FloatRamp" ) + floatRamp["parameters"]["x"].setInput( g["out"]["globalV"] ) + floatRamp['parameters']['ramp'].setValue( IECore.Rampff( ( ( 1/8, 0 ), ( 3/8, 0 ), ( 5/8, 1 ), ( 7/8, 1 )), IECore.RampInterpolation.Constant ) ) + floatRamp["parameters"]["ramp"]["p1"]["y"].setInput( invertU["out"]["out"] ) + floatRamp["parameters"]["ramp"]["p2"]["y"].setInput( g["out"]["globalU"] ) oslImage = GafferOSL.OSLImage() oslImage["channels"].addChild( Gaffer.NameValuePlug( "", Gaffer.Color3fPlug( "value" ), True, "channel" ) ) oslImage["defaultFormat"].setValue( GafferImage.Format( 2, 8, 1.000 ) ) - oslImage["channels"]["channel"]["value"].setInput( floatSpline["out"]["c"] ) + oslImage["channels"]["channel"]["value"].setInput( floatRamp["out"]["c"] ) def testEval( channelName ): d = oslImage['out'].channelData( channelName, imath.V2i( 0 ) ) @@ -936,50 +938,56 @@ def testEval( channelName ): self.assertEqual( testEval("R"), [0, 0, 0, 0, 0, 0, 750, 250, 750, 250, 250, 750, 250, 750, 1000, 1000] ) - floatSpline["parameters"]["spline"]["interpolation"].setValue( Gaffer.SplineDefinitionInterpolation.Linear ) + floatRamp["parameters"]["ramp"]["interpolation"].setValue( IECore.RampInterpolation.Linear ) self.assertEqual( testEval("R"), [0, 0, 188, 62, 562, 188, 625, 375, 375, 625, 438, 812, 812, 938, 1000, 1000] ) - floatSpline["parameters"]["spline"]["interpolation"].setValue( Gaffer.SplineDefinitionInterpolation.CatmullRom ) + floatRamp["parameters"]["ramp"]["interpolation"].setValue( IECore.RampInterpolation.CatmullRom ) self.assertEqual( testEval("R"), [0, 0, 232, 54, 648, 170, 684, 363, 316, 637, 352, 830, 768, 946, 1000, 1000] ) - floatSpline["parameters"]["spline"]["interpolation"].setValue( Gaffer.SplineDefinitionInterpolation.BSpline ) + floatRamp["parameters"]["ramp"]["interpolation"].setValue( IECore.RampInterpolation.BSpline ) self.assertEqual( testEval("R"), [0, 0, 187, 63, 476, 205, 540, 392, 460, 608, 524, 795, 813, 937, 1000, 1000] ) - floatSpline["parameters"]["spline"]["interpolation"].setValue( Gaffer.SplineDefinitionInterpolation.MonotoneCubic ) - with self.assertRaisesRegex( Exception, "Cannot support monotone cubic interpolation for splines with inputs, for plug OSLShader.parameters.s" ): + floatRamp["parameters"]["ramp"]["interpolation"].setValue( IECore.RampInterpolation.MonotoneCubic ) + with IECore.CapturingMessageHandler() as mh : testEval( "R" ) + self.assertEqual( len( mh.messages ), 1 ) + self.assertEqual( mh.messages[0].message, + "Cannot connect adaptors to ramp when using monotoneCubic interpolation: OSLShader2.ramp[1].y" + ) + self.assertEqual( mh.messages[0].level, IECore.Msg.Level.Error ) + # Make connections to outermost control points ( this will require duplicating connections to the # duplicated end points ) - floatSpline["parameters"]["spline"]["p0"]["y"].setInput( invertU["out"]["out"] ) - floatSpline["parameters"]["spline"]["p1"]["y"].setInput( None ) - floatSpline["parameters"]["spline"]["p2"]["y"].setInput( None ) - floatSpline["parameters"]["spline"]["p3"]["y"].setInput( g["out"]["globalU"] ) + floatRamp["parameters"]["ramp"]["p0"]["y"].setInput( invertU["out"]["out"] ) + floatRamp["parameters"]["ramp"]["p1"]["y"].setInput( None ) + floatRamp["parameters"]["ramp"]["p2"]["y"].setInput( None ) + floatRamp["parameters"]["ramp"]["p3"]["y"].setInput( g["out"]["globalU"] ) - floatSpline["parameters"]["spline"]["interpolation"].setValue( Gaffer.SplineDefinitionInterpolation.Constant ) + floatRamp["parameters"]["ramp"]["interpolation"].setValue( IECore.RampInterpolation.Constant ) self.assertEqual( testEval("R"), [750, 250, 750, 250, 750, 250, 0, 0, 0, 0, 1000, 1000, 1000, 1000, 250, 750]) - floatSpline["parameters"]["spline"]["interpolation"].setValue( Gaffer.SplineDefinitionInterpolation.Linear ) + floatRamp["parameters"]["ramp"]["interpolation"].setValue( IECore.RampInterpolation.Linear ) self.assertEqual( testEval("R"), [750, 250, 562, 188, 188, 62, 250, 250, 750, 750, 812, 938, 438, 812, 250, 750] ) - floatSpline["parameters"]["spline"]["interpolation"].setValue( Gaffer.SplineDefinitionInterpolation.CatmullRom ) + floatRamp["parameters"]["ramp"]["interpolation"].setValue( IECore.RampInterpolation.CatmullRom ) self.assertEqual( testEval("R"), [750, 250, 500, 143, 68, -23, 168, 191, 832, 809, 932, 1023, 500, 857, 250, 750] ) - floatSpline["parameters"]["spline"]["interpolation"].setValue( Gaffer.SplineDefinitionInterpolation.BSpline ) + floatRamp["parameters"]["ramp"]["interpolation"].setValue( IECore.RampInterpolation.BSpline ) self.assertEqual( testEval("R"), [750, 250, 563, 188, 309, 149, 368, 335, 632, 665, 691, 851, 437, 812, 250, 750] ) # Now test color connections - colorSpline = GafferOSL.OSLShader() - colorSpline.loadShader( "Pattern/ColorSpline" ) - colorSpline["parameters"]["x"].setInput( g["out"]["globalV"] ) + colorRamp = GafferOSL.OSLShader() + colorRamp.loadShader( "Pattern/ColorRamp" ) + colorRamp["parameters"]["x"].setInput( g["out"]["globalV"] ) - colorSpline['parameters']['spline'].setValue( Gaffer.SplineDefinitionfColor3f( + colorRamp['parameters']['ramp'].setValue( IECore.RampfColor3f( ( ( 1/8, imath.Color3f(0, 1, 0.4) ), ( 3/8, imath.Color3f(0.25, 0.75, 0.5) ), ( 5/8, imath.Color3f(0.75, 0.25, 0.6) ), ( 7/8, imath.Color3f(1, 0, 0.7) ) ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) ) floatToColor = GafferOSL.OSLShader() @@ -988,20 +996,20 @@ def testEval( channelName ): floatToColor["parameters"]["g"].setValue( 0.55 ) floatToColor["parameters"]["b"].setInput( g["out"]["globalU"] ) - colorSpline["parameters"]["spline"]["p1"]["y"].setInput( floatToColor["out"]["c"] ) - colorSpline["parameters"]["spline"]["p3"]["y"]["g"].setInput( g["out"]["globalU"] ) + colorRamp["parameters"]["ramp"]["p1"]["y"].setInput( floatToColor["out"]["c"] ) + colorRamp["parameters"]["ramp"]["p3"]["y"]["g"].setInput( g["out"]["globalU"] ) - oslImage["channels"]["channel"]["value"].setInput( colorSpline["out"]["c"] ) + oslImage["channels"]["channel"]["value"].setInput( colorRamp["out"]["c"] ) self.assertEqual( testEval("R"), [0, 0, 214, 54, 614, 170, 797, 363, 750, 637, 795, 830, 929, 946, 1000, 1000]) self.assertEqual( testEval("G"), [1000, 1000, 882, 882, 652, 652, 457, 446, 300, 265, 230, 320, 239, 597, 250, 750] ) self.assertEqual( testEval("B"), [400, 400, 345, 505, 253, 697, 308, 742, 518, 632, 642, 608, 684, 666, 700, 700] ) # Modify x value ordering to make sure that control point sorting is working - colorSpline["parameters"]["spline"]["p0"]["x"].setValue( 7/8 ) - colorSpline["parameters"]["spline"]["p1"]["x"].setValue( 5/8 ) - colorSpline["parameters"]["spline"]["p2"]["x"].setValue( 3/8 ) - colorSpline["parameters"]["spline"]["p3"]["x"].setValue( 1/8 ) + colorRamp["parameters"]["ramp"]["p0"]["x"].setValue( 7/8 ) + colorRamp["parameters"]["ramp"]["p1"]["x"].setValue( 5/8 ) + colorRamp["parameters"]["ramp"]["p2"]["x"].setValue( 3/8 ) + colorRamp["parameters"]["ramp"]["p3"]["x"].setValue( 1/8 ) self.assertEqual( testEval("R"), [ 1000, 1000, 929, 946, 795, 830, 750, 637, 797, 363, 614, 170, 214, 54, 0, 0 ]) self.assertEqual( testEval("G"), [ 250, 750, 239, 597, 230, 320, 300, 265, 457, 446, 652, 652, 882, 882, 1000, 1000 ] ) diff --git a/python/GafferOSLTest/OSLShaderTest.py b/python/GafferOSLTest/OSLShaderTest.py index 1d7da9db34..20b1fa509b 100644 --- a/python/GafferOSLTest/OSLShaderTest.py +++ b/python/GafferOSLTest/OSLShaderTest.py @@ -451,7 +451,7 @@ def testParameterSplineMetadata( self ) : n = GafferOSL.OSLShader() n.loadShader( s ) - # If the components of the spline all match, the metadata is registered to the spline plug + # If the components of the spline all match, the metadata is registered to the ramp plug self.assertEqual( n.parameterMetadata( n["parameters"]["correctSpline"], "a" ), 1 ) self.assertEqual( n.parameterMetadata( n["parameters"]["correctSpline"], "b" ), 2 ) self.assertEqual( n.parameterMetadata( n["parameters"]["correctSpline"], "c" ), 3 ) @@ -698,9 +698,9 @@ def testSplineParameters( self ) : self.assertEqual( n["parameters"].keys(), [ "floatSpline", "colorSpline", "checkLinearSpline", "constDefault" ] ) - self.assertTrue( isinstance( n["parameters"]["floatSpline"], Gaffer.SplineffPlug ) ) + self.assertTrue( isinstance( n["parameters"]["floatSpline"], Gaffer.RampffPlug ) ) self.assertEqual( - n["parameters"]["floatSpline"].getValue().spline(), + n["parameters"]["floatSpline"].getValue().evaluator(), IECore.Splineff( IECore.CubicBasisf.catmullRom(), [ @@ -712,9 +712,9 @@ def testSplineParameters( self ) : ) ) - self.assertTrue( isinstance( n["parameters"]["colorSpline"], Gaffer.SplinefColor3fPlug ) ) + self.assertTrue( isinstance( n["parameters"]["colorSpline"], Gaffer.RampfColor3fPlug ) ) self.assertEqual( - n["parameters"]["colorSpline"].getValue().spline(), + n["parameters"]["colorSpline"].getValue().evaluator(), IECore.SplinefColor3f( IECore.CubicBasisf.bSpline(), [ @@ -728,9 +728,9 @@ def testSplineParameters( self ) : ) ) - self.assertTrue( isinstance( n["parameters"]["checkLinearSpline"], Gaffer.SplineffPlug ) ) + self.assertTrue( isinstance( n["parameters"]["checkLinearSpline"], Gaffer.RampffPlug ) ) self.assertEqual( - n["parameters"]["checkLinearSpline"].getValue().spline(), + n["parameters"]["checkLinearSpline"].getValue().evaluator(), IECore.Splineff( IECore.CubicBasisf.linear(), [ @@ -740,9 +740,9 @@ def testSplineParameters( self ) : ) ) - self.assertTrue( isinstance( n["parameters"]["constDefault"], Gaffer.SplinefColor3fPlug ) ) + self.assertTrue( isinstance( n["parameters"]["constDefault"], Gaffer.RampfColor3fPlug ) ) self.assertEqual( - n["parameters"]["constDefault"].getValue().spline(), + n["parameters"]["constDefault"].getValue().evaluator(), IECore.SplinefColor3f( IECore.CubicBasisf.constant(), [ @@ -755,29 +755,23 @@ def testSplineParameters( self ) : self.assertEqual( shader.parameters["floatSpline"].value, - IECore.Splineff( - IECore.CubicBasisf.catmullRom(), + IECore.Rampff( [ - ( 0, 0 ), ( 0, 0 ), ( 1, 1 ), - ( 1, 1 ), - ] + ], + IECore.RampInterpolation.CatmullRom ) ) self.assertEqual( shader.parameters["colorSpline"].value, - IECore.SplinefColor3f( - IECore.CubicBasisf.bSpline(), + IECore.RampfColor3f( [ - ( 0, imath.Color3f( 0 ) ), - ( 0, imath.Color3f( 0 ) ), ( 0, imath.Color3f( 0 ) ), ( 1, imath.Color3f( 1 ) ), - ( 1, imath.Color3f( 1 ) ), - ( 1, imath.Color3f( 1 ) ), - ] + ], + IECore.RampInterpolation.BSpline ) ) @@ -792,9 +786,9 @@ def testSplineParametersTooShort( self ) : self.assertEqual( n["parameters"].keys(), [ "colorSpline" ] ) - self.assertTrue( isinstance( n["parameters"]["colorSpline"], Gaffer.SplinefColor3fPlug ) ) + self.assertTrue( isinstance( n["parameters"]["colorSpline"], Gaffer.RampfColor3fPlug ) ) self.assertEqual( - n["parameters"]["colorSpline"].getValue().spline(), + n["parameters"]["colorSpline"].getValue().evaluator(), IECore.SplinefColor3f( IECore.CubicBasisf.linear(), [ @@ -828,9 +822,9 @@ def test3delightSplineParameters( self ) : ] ) - self.assertTrue( isinstance( n["parameters"]["floatSpline"], Gaffer.SplineffPlug ) ) + self.assertTrue( isinstance( n["parameters"]["floatSpline"], Gaffer.RampffPlug ) ) self.assertEqual( - n["parameters"]["floatSpline"].getValue().spline(), + n["parameters"]["floatSpline"].getValue().evaluator(), IECore.Splineff( IECore.CubicBasisf.linear(), [ @@ -840,9 +834,9 @@ def test3delightSplineParameters( self ) : ) ) - self.assertTrue( isinstance( n["parameters"]["colorSpline"], Gaffer.SplinefColor3fPlug ) ) + self.assertTrue( isinstance( n["parameters"]["colorSpline"], Gaffer.RampfColor3fPlug ) ) self.assertEqual( - n["parameters"]["colorSpline"].getValue().spline(), + n["parameters"]["colorSpline"].getValue().evaluator(), IECore.SplinefColor3f( IECore.CubicBasisf.catmullRom(), [ @@ -854,9 +848,9 @@ def test3delightSplineParameters( self ) : ) ) - self.assertTrue( isinstance( n["parameters"]["dualInterpolationSpline"], Gaffer.SplineffPlug ) ) + self.assertTrue( isinstance( n["parameters"]["dualInterpolationSpline"], Gaffer.RampffPlug ) ) self.assertEqual( - n["parameters"]["dualInterpolationSpline"].getValue().spline(), + n["parameters"]["dualInterpolationSpline"].getValue().evaluator(), IECore.Splineff( IECore.CubicBasisf.linear(), [ @@ -873,9 +867,9 @@ def test3delightSplineParameters( self ) : IECore.IntVectorData( [ -1 ] ) ) - self.assertTrue( isinstance( n["parameters"]["trimmedFloatSpline"], Gaffer.SplineffPlug ) ) + self.assertTrue( isinstance( n["parameters"]["trimmedFloatSpline"], Gaffer.RampffPlug ) ) self.assertEqual( - n["parameters"]["trimmedFloatSpline"].getValue().spline(), + n["parameters"]["trimmedFloatSpline"].getValue().evaluator(), IECore.Splineff( IECore.CubicBasisf.catmullRom(), [ @@ -887,9 +881,9 @@ def test3delightSplineParameters( self ) : ) ) - self.assertTrue( isinstance( n["parameters"]["mayaSpline"], Gaffer.SplineffPlug ) ) + self.assertTrue( isinstance( n["parameters"]["mayaSpline"], Gaffer.RampffPlug ) ) self.assertEqual( - n["parameters"]["mayaSpline"].getValue().spline(), + n["parameters"]["mayaSpline"].getValue().evaluator(), IECore.Splineff( IECore.CubicBasisf.linear(), [ @@ -899,22 +893,22 @@ def test3delightSplineParameters( self ) : ) ) - self.assertTrue( isinstance( n["parameters"]["inconsistentNameSpline"], Gaffer.SplineffPlug ) ) + self.assertTrue( isinstance( n["parameters"]["inconsistentNameSpline"], Gaffer.RampffPlug ) ) self.assertEqual( - n["parameters"]["inconsistentNameSpline"].getValue().spline(), - Gaffer.SplineDefinitionff( + n["parameters"]["inconsistentNameSpline"].getValue(), + IECore.Rampff( ((0,0), (1,1)), - Gaffer.SplineDefinitionInterpolation.MonotoneCubic - ).spline() + IECore.RampInterpolation.MonotoneCubic + ) ) - self.assertTrue( isinstance( n["parameters"]["inconsistentNameOtherSpline"], Gaffer.SplineffPlug ) ) + self.assertTrue( isinstance( n["parameters"]["inconsistentNameOtherSpline"], Gaffer.RampffPlug ) ) self.assertEqual( - n["parameters"]["inconsistentNameSpline"].getValue().spline(), - Gaffer.SplineDefinitionff( + n["parameters"]["inconsistentNameSpline"].getValue().evaluator(), + IECore.Rampff( ((0, 0), (1,1)), - Gaffer.SplineDefinitionInterpolation.MonotoneCubic - ).spline() + IECore.RampInterpolation.MonotoneCubic + ).evaluator() ) def testRmanSplineParameters( self ) : @@ -943,9 +937,9 @@ def testRmanSplineParameters( self ) : ] ) - self.assertTrue( isinstance( n["parameters"]["floatRamp"], Gaffer.SplineffPlug ) ) + self.assertTrue( isinstance( n["parameters"]["floatRamp"], Gaffer.RampffPlug ) ) self.assertEqual( - n["parameters"]["floatRamp"].getValue().spline(), + n["parameters"]["floatRamp"].getValue().evaluator(), IECore.Splineff( IECore.CubicBasisf.linear(), [ @@ -955,9 +949,9 @@ def testRmanSplineParameters( self ) : ) ) - self.assertTrue( isinstance( n["parameters"]["colorRamp"], Gaffer.SplinefColor3fPlug ) ) + self.assertTrue( isinstance( n["parameters"]["colorRamp"], Gaffer.RampfColor3fPlug ) ) self.assertEqual( - n["parameters"]["colorRamp"].getValue().spline(), + n["parameters"]["colorRamp"].getValue().evaluator(), IECore.SplinefColor3f( IECore.CubicBasisf.catmullRom(), [ @@ -969,17 +963,17 @@ def testRmanSplineParameters( self ) : ) ) - self.assertTrue( isinstance( n["parameters"]["mismatchedRamp"], Gaffer.SplinefColor3fPlug ) ) + self.assertTrue( isinstance( n["parameters"]["mismatchedRamp"], Gaffer.RampfColor3fPlug ) ) self.assertEqual( - n["parameters"]["mismatchedRamp"].getValue().spline(), - IECore.SplinefColor3f( - IECore.CubicBasisf.catmullRom(), + n["parameters"]["mismatchedRamp"].getValue(), + IECore.RampfColor3f( [ ( 0, imath.Color3f( 1, 2, 3 ) ), - ( 0, imath.Color3f( 1, 2, 3 ) ), + ( 0.25, imath.Color3f( 1, 2, 3 ) ), + ( 0.75, imath.Color3f( 4, 5, 6 ) ), ( 1, imath.Color3f( 4, 5, 6 ) ), - ( 1, imath.Color3f( 4, 5, 6 ) ), - ] + ], + IECore.RampInterpolation.CatmullRom ) ) @@ -1009,17 +1003,17 @@ def testSplineParameterEvaluation( self ) : image["shader"].setInput( n["out"]["out"] ) for interpolation in [ - Gaffer.SplineDefinitionInterpolation.Linear, - Gaffer.SplineDefinitionInterpolation.CatmullRom, - Gaffer.SplineDefinitionInterpolation.BSpline, - Gaffer.SplineDefinitionInterpolation.MonotoneCubic + IECore.RampInterpolation.Linear, + IECore.RampInterpolation.CatmullRom, + IECore.RampInterpolation.BSpline, + IECore.RampInterpolation.MonotoneCubic ]: - n["parameters"]["colorSpline"].setValue( Gaffer.SplineDefinitionfColor3f( points, interpolation ) ) + n["parameters"]["colorSpline"].setValue( IECore.RampfColor3f( points, interpolation ) ) oslSamples = list( reversed( GafferImage.ImageAlgo.image( image['out'] )["R"] ) ) - s = n['parameters']['colorSpline'].getValue().spline() + s = n['parameters']['colorSpline'].getValue().evaluator() cortexSamples = [ s( ( i + 0.5 ) / numSamples )[0] for i in range( numSamples ) ] for a, b in zip( oslSamples, cortexSamples ): @@ -1218,9 +1212,9 @@ def testSplineParameterSerialisation( self ) : s['n'] = GafferOSL.OSLShader() s['n'].loadShader( shad ) - splineValue = Gaffer.SplineDefinitionfColor3f( [ ( random.random(), imath.Color3f( random.random(), random.random(), random.random() ) ) for i in range( 10 ) ], Gaffer.SplineDefinitionInterpolation.Linear ) + rampValue = IECore.RampfColor3f( [ ( random.random(), imath.Color3f( random.random(), random.random(), random.random() ) ) for i in range( 10 ) ], IECore.RampInterpolation.Linear ) - s['n']["parameters"]["colorSpline"].setValue( splineValue ) + s['n']["parameters"]["colorSpline"].setValue( rampValue ) serialised = s.serialise() @@ -1234,7 +1228,7 @@ def testSplineParameterSerialisation( self ) : s2 = Gaffer.ScriptNode() s2.execute( serialised ) - self.assertEqual( s2['n']["parameters"]["colorSpline"].getValue(), splineValue ) + self.assertEqual( s2['n']["parameters"]["colorSpline"].getValue(), rampValue ) def testComponentToComponentConnections( self ) : diff --git a/python/GafferOSLTest/ShadingEngineTest.py b/python/GafferOSLTest/ShadingEngineTest.py index e74c2149df..d4a872225d 100644 --- a/python/GafferOSLTest/ShadingEngineTest.py +++ b/python/GafferOSLTest/ShadingEngineTest.py @@ -484,25 +484,26 @@ def testDebugClosureWithZeroValue( self ) : def testSpline( self ) : shader = self.compileShader( pathlib.Path( __file__ ).parent / "shaders" / "splineParameters.osl" ) - spline = IECore.SplinefColor3f( - IECore.CubicBasisf.bSpline(), + ramp = IECore.RampfColor3f( [ ( 0, imath.Color3f( 1 ) ), - ( 0, imath.Color3f( 1 ) ), - ( 1, imath.Color3f( 0 ) ), + ( 0.25, imath.Color3f( 1 ) ), + ( 0.75, imath.Color3f( 0 ) ), ( 1, imath.Color3f( 0 ) ), - ] + ], + IECore.RampInterpolation.BSpline ) e = GafferOSL.ShadingEngine( IECoreScene.ShaderNetwork( shaders = { - "output" : IECoreScene.Shader( shader, "osl:surface", { "colorSpline" : spline } ) + "output" : IECoreScene.Shader( shader, "osl:surface", { "colorSpline" : ramp } ) }, output = "output" ) ) rp = self.rectanglePoints() p = e.shade( rp ) + spline = ramp.evaluator() for i in range( 0, len( p["Ci"] ) ) : self.assertTrue( p["Ci"][i].equalWithAbsError( spline( rp["v"][i] ), 0.001 ) ) diff --git a/python/GafferOSLTest/shaders/PxrSplineParameters.osl b/python/GafferOSLTest/shaders/PxrSplineParameters.osl index b89c5bb303..982aae5d07 100644 --- a/python/GafferOSLTest/shaders/PxrSplineParameters.osl +++ b/python/GafferOSLTest/shaders/PxrSplineParameters.osl @@ -53,7 +53,7 @@ shader PxrSplineParameters // Matches convention used by PxrStylizedControl. It appears the expectation is that we should trim the default // values to the length given in the first parameter. int mismatchedRamp = 4, - float mismatchedRamp_Knots[] = { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + float mismatchedRamp_Knots[] = { 0, 0.25, 0.75, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }, color mismatchedRamp_Colors[] = { color( 1, 2, 3 ), color( 1, 2, 3 ), color( 4, 5, 6 ), color( 4, 5, 6 ), 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 }, string mismatchedRamp_Interpolation = "catmull-rom", diff --git a/python/GafferOSLUI/OSLCodeUI.py b/python/GafferOSLUI/OSLCodeUI.py index 0258f973eb..4351dd35a9 100644 --- a/python/GafferOSLUI/OSLCodeUI.py +++ b/python/GafferOSLUI/OSLCodeUI.py @@ -96,7 +96,7 @@ - M44fPlug (`matrix`) - StringPlug (`string`) - ClosurePlug (`closure color`) - - SplinefColor3f ( triplet of `float [], color [], string` ) + - RampfColor3fPlug ( triplet of `float [], color [], string` ) """, "layout:customWidget:footer:widgetType" : "GafferOSLUI.OSLCodeUI._ParametersFooter", @@ -121,7 +121,7 @@ """ The outputs from the shader. Any number of outputs may be created by adding child plugs. Supported plug types are as for the input - parameters, with the exception of SplinefColor3f, which cannot be + parameters, with the exception of RampfColor3fPlug, which cannot be used as an output. """, @@ -212,17 +212,15 @@ def __menuDefinition( self ) : labelsAndConstructors.insert( -1, - ( "Color Spline", + ( "Color Ramp", functools.partial( - Gaffer.SplinefColor3fPlug, - defaultValue = IECore.SplinefColor3f( - IECore.CubicBasisf.catmullRom(), + Gaffer.RampfColor3fPlug, + defaultValue = IECore.RampfColor3f( ( ( 0, imath.Color3f( 0 ) ), - ( 0, imath.Color3f( 0 ) ), - ( 1, imath.Color3f( 1 ) ), ( 1, imath.Color3f( 1 ) ), - ) + ), + IECore.RampInterpolation.CatmullRom ) ) ) @@ -305,7 +303,7 @@ def __dropText( self, widget, dragData ) : if plug.parent() not in ( node["parameters"], node["out"] ) : return None - if isinstance( plug, Gaffer.SplinefColor3fPlug ) : + if isinstance( plug, Gaffer.RampfColor3fPlug ) : return "colorSpline( {0}Positions, {0}Values, {0}Basis, u )".format( plug.getName() ) return plug.getName() diff --git a/python/GafferOSLUI/OSLShaderUI.py b/python/GafferOSLUI/OSLShaderUI.py index 1df01ecefd..be3c7eab60 100644 --- a/python/GafferOSLUI/OSLShaderUI.py +++ b/python/GafferOSLUI/OSLShaderUI.py @@ -142,7 +142,7 @@ def __plugWidgetType( plug ) : def __plugNoduleType( plug ) : - if isinstance( plug, ( Gaffer.SplinefColor3fPlug, Gaffer.SplineffPlug ) ) : + if isinstance( plug, ( Gaffer.RampfColor3fPlug, Gaffer.RampffPlug ) ) : return "" elif plug.node().parameterMetadata( plug, "connectable" ) == 0 : return "" diff --git a/python/GafferOSLUITest/OSLShaderUITest.py b/python/GafferOSLUITest/OSLShaderUITest.py index 64c297e212..da736c4d4d 100644 --- a/python/GafferOSLUITest/OSLShaderUITest.py +++ b/python/GafferOSLUITest/OSLShaderUITest.py @@ -38,6 +38,8 @@ import imath +import IECore + import Gaffer import GafferUI @@ -93,24 +95,24 @@ def testParameterUserDefaults( self ) : self.assertEqual( s["parameters"]["name"].getValue(), "xx" ) self.assertEqual( s["parameters"]["defaultValue"].getValue(), 1 ) - def testSplineParameterUserDefaults( self ) : + def testRampParameterUserDefaults( self ) : Gaffer.Metadata.registerValue( - "osl:shader:Pattern/ColorSpline:spline.interpolation", "userDefault", - Gaffer.SplineDefinitionInterpolation.Linear + "osl:shader:Pattern/ColorRamp:ramp.interpolation", "userDefault", + IECore.RampInterpolation.Linear ) s = GafferOSL.OSLShader() - s.loadShader( "Pattern/ColorSpline" ) + s.loadShader( "Pattern/ColorRamp" ) Gaffer.NodeAlgo.applyUserDefaults( s ) - self.assertEqual( s["parameters"]["spline"]["interpolation"].getValue(), Gaffer.SplineDefinitionInterpolation.Linear ) + self.assertEqual( s["parameters"]["ramp"]["interpolation"].getValue(), IECore.RampInterpolation.Linear ) Gaffer.Metadata.registerValue( - "osl:shader:Pattern/ColorSpline:spline.interpolation", "userDefault", - Gaffer.SplineDefinitionInterpolation.MonotoneCubic + "osl:shader:Pattern/ColorRamp:ramp.interpolation", "userDefault", + IECore.RampInterpolation.MonotoneCubic ) Gaffer.NodeAlgo.applyUserDefaults( s ) - self.assertEqual( s["parameters"]["spline"]["interpolation"].getValue(), Gaffer.SplineDefinitionInterpolation.MonotoneCubic ) + self.assertEqual( s["parameters"]["ramp"]["interpolation"].getValue(), IECore.RampInterpolation.MonotoneCubic ) def testActivatorMetadata( self ) : @@ -159,7 +161,7 @@ def tearDown( self ) : Gaffer.Metadata.deregisterValue( "osl:shader:ObjectProcessing/InFloat:name", "userDefault" ) Gaffer.Metadata.deregisterValue( "osl:shader:ObjectProcessing/InFloat:defaultValue", "userDefault" ) - Gaffer.Metadata.deregisterValue( "osl:shader:Pattern/ColorSpline:spline.interpolation", "userDefault" ) + Gaffer.Metadata.deregisterValue( "osl:shader:Pattern/ColorRamp:ramp.interpolation", "userDefault" ) if __name__ == "__main__": unittest.main() diff --git a/python/GafferRenderManTest/RenderManShaderTest.py b/python/GafferRenderManTest/RenderManShaderTest.py index 86ea44f59b..0138ca2ef1 100644 --- a/python/GafferRenderManTest/RenderManShaderTest.py +++ b/python/GafferRenderManTest/RenderManShaderTest.py @@ -38,6 +38,7 @@ import imath +import IECore import IECoreRenderMan import Gaffer @@ -328,7 +329,7 @@ def testSplines( self ) : self.assertEqual( shader['parameters']['targetHue'].getFlags(), Gaffer.Plug.Flags.Default ) self.assertEqual( shader['parameters']['targetHue'].direction(), Gaffer.Plug.Direction.In ) self.assertEqual( shader['parameters']['targetHue'].defaultValue(), - Gaffer.SplineDefinitionfColor3f( + IECore.RampfColor3f( ( ( 0, imath.Color3f( 1, 0.25, 0.25 ) ), ( 0.166, imath.Color3f( 1, 1, 0.25 ) ), @@ -338,19 +339,19 @@ def testSplines( self ) : ( 0.833, imath.Color3f( 1, 0.25, 1 ) ), ( 1, imath.Color3f( 1, 0.25, 0.25 ) ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) ) self.assertEqual( shader['parameters']['incidentAngle'].getFlags(), Gaffer.Plug.Flags.Default ) self.assertEqual( shader['parameters']['incidentAngle'].direction(), Gaffer.Plug.Direction.In ) self.assertEqual( shader['parameters']['incidentAngle'].defaultValue(), - Gaffer.SplineDefinitionff( + IECore.Rampff( ( ( 0, 0 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.Linear + IECore.RampInterpolation.Linear ) ) @@ -379,12 +380,12 @@ def testSplines( self ) : self.assertEqual( shader['parameters']['ramp'].getFlags(), Gaffer.Plug.Flags.Default ) self.assertEqual( shader['parameters']['ramp'].direction(), Gaffer.Plug.Direction.In ) self.assertEqual( shader['parameters']['ramp'].defaultValue(), - Gaffer.SplineDefinitionff( + IECore.Rampff( ( ( 0, 0 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.Linear + IECore.RampInterpolation.Linear ) ) diff --git a/python/GafferSceneTest/ImageScatterTest.py b/python/GafferSceneTest/ImageScatterTest.py index 03a2e8a105..e7c53c9db0 100644 --- a/python/GafferSceneTest/ImageScatterTest.py +++ b/python/GafferSceneTest/ImageScatterTest.py @@ -94,7 +94,7 @@ def testPrimitiveVariables( self ) : ramp["startPosition"].setValue( imath.V2f( 0.5, 0 ) ) ramp["endPosition"].setValue( imath.V2f( 2.5, 0 ) ) ramp["ramp"]["p0"]["y"]["a"].setValue( 1 ) # Solid alpha - ramp["ramp"]["interpolation"].setValue( Gaffer.SplineDefinitionInterpolation.Linear ) + ramp["ramp"]["interpolation"].setValue( IECore.RampInterpolation.Linear ) scatter = GafferScene.ImageScatter() scatter["image"].setInput( ramp["out"] ) @@ -122,7 +122,7 @@ def testPrimitiveVariables( self ) : self.assertEqual( len( points["width"].data ), len( points["P"].data ) ) for i, c in enumerate( points["Cs"].data ) : - # Expected spline value + # Expected ramp value x = points["P"].data[i].x / pixelAspect x = (x - 0.5) / 2.0 x = max( 0, min( x, 1 ) ) diff --git a/python/GafferSceneTest/ImageToPointsTest.py b/python/GafferSceneTest/ImageToPointsTest.py index 72ab028e5c..b825d450f5 100644 --- a/python/GafferSceneTest/ImageToPointsTest.py +++ b/python/GafferSceneTest/ImageToPointsTest.py @@ -134,11 +134,11 @@ def testPrimitiveVariables( self ) : rampStart = imath.Color4f( 1, 0.5, 0, 1 ) rampEnd = imath.Color4f( 0, 0.5, 1, 1 ) ramp["ramp"].setValue( - Gaffer.SplineDefinitionfColor4f( + IECore.RampfColor4f( ( ( 0, rampStart ), ( 1, rampEnd ), - ), Gaffer.SplineDefinitionInterpolation.Constant + ), IECore.RampInterpolation.Constant ) ) @@ -235,11 +235,11 @@ def testAlpha( self ) : rampStart = imath.Color4f( 1, 0.5, 0, 0 ) rampEnd = imath.Color4f( 0, 0.5, 1, 1 ) ramp["ramp"].setValue( - Gaffer.SplineDefinitionfColor4f( + IECore.RampfColor4f( ( ( 0, rampStart ), ( 1, rampEnd ), - ), Gaffer.SplineDefinitionInterpolation.Constant + ), IECore.RampInterpolation.Constant ) ) diff --git a/python/GafferSceneTest/ShaderTest.py b/python/GafferSceneTest/ShaderTest.py index a6ebd6223b..3fc3dccdd2 100644 --- a/python/GafferSceneTest/ShaderTest.py +++ b/python/GafferSceneTest/ShaderTest.py @@ -187,7 +187,7 @@ def testParameterValuesWhenConnected( self ) : # connected shader's output as the correct type self.assertEqual( network.getShader( "n3" ).parameters, - IECore.CompoundData( { "i" : IECore.IntData( 0 ), "c" : IECore.Color3fData( imath.Color3f( 0 ) ), "spline" : IECore.SplinefColor3fData() } ) + IECore.CompoundData( { "i" : IECore.IntData( 0 ), "c" : IECore.Color3fData( imath.Color3f( 0 ) ), "ramp" : IECore.RampfColor3fData() } ) ) def testDetectCyclicConnections( self ) : @@ -637,66 +637,60 @@ def testSpline( self ) : network = n1.attributes()["test:surface"] - self.assertEqual( network.shaders()["n1"].parameters["spline"], IECore.SplinefColor3fData() ) + self.assertEqual( network.shaders()["n1"].parameters["ramp"], IECore.RampfColor3fData() ) - n1["parameters"]["spline"].addPoint() - n1["parameters"]["spline"].addPoint() - n1["parameters"]["spline"].addPoint() - n1["parameters"]["spline"]["p1"]["x"].setValue( 1 ) - n1["parameters"]["spline"]["p1"]["y"].setValue( imath.Color3f( 1 ) ) - n1["parameters"]["spline"]["p2"]["x"].setValue( 0.6 ) - n1["parameters"]["spline"]["p2"]["y"].setValue( imath.Color3f( 0.4, 0.5, 0.7 ) ) + n1["parameters"]["ramp"].addPoint() + n1["parameters"]["ramp"].addPoint() + n1["parameters"]["ramp"].addPoint() + n1["parameters"]["ramp"]["p1"]["x"].setValue( 1 ) + n1["parameters"]["ramp"]["p1"]["y"].setValue( imath.Color3f( 1 ) ) + n1["parameters"]["ramp"]["p2"]["x"].setValue( 0.6 ) + n1["parameters"]["ramp"]["p2"]["y"].setValue( imath.Color3f( 0.4, 0.5, 0.7 ) ) network = n1.attributes()["test:surface"] - refSpline = IECore.SplinefColor3f() - refSpline[0] = imath.Color3f( 0 ) - refSpline[0] = imath.Color3f( 0 ) - refSpline[0.6] = imath.Color3f( 0.4, 0.5, 0.7 ) - refSpline[1] = imath.Color3f( 1 ) - refSpline[1] = imath.Color3f( 1 ) + refSpline = IECore.RampfColor3f( + [ ( 0, imath.Color3f( 0 ) ), ( 0.6, imath.Color3f( 0.4, 0.5, 0.7 ) ), ( 1, imath.Color3f( 1 ) ) ], + IECore.RampInterpolation.CatmullRom + ) - self.assertEqual( network.shaders()["n1"].parameters["spline"].value, refSpline ) + self.assertEqual( network.shaders()["n1"].parameters["ramp"].value, refSpline ) inN1 = GafferSceneTest.TestShader( "inN1" ) - n1["parameters"]["spline"]["p0"]["y"].setInput( inN1["out"]["c"] ) - n1["parameters"]["spline"]["p1"]["y"]["b"].setInput( inN1["out"]["c"]["g"] ) + n1["parameters"]["ramp"]["p0"]["y"].setInput( inN1["out"]["c"] ) + n1["parameters"]["ramp"]["p1"]["y"]["b"].setInput( inN1["out"]["c"]["g"] ) network = n1.attributes()["test:surface"] self.assertEqual( len( network ), 2 ) self.assertEqual( network.inputConnections( "n1" ), [ - network.Connection( network.Parameter( "inN1", "c", ), network.Parameter( "n1", "spline[0].y" ) ), - network.Connection( network.Parameter( "inN1", "c", ), network.Parameter( "n1", "spline[1].y" ) ), - network.Connection( network.Parameter( "inN1", "c.g", ), network.Parameter( "n1", "spline[3].y.b" ) ), - network.Connection( network.Parameter( "inN1", "c.g", ), network.Parameter( "n1", "spline[4].y.b" ) ) + network.Connection( network.Parameter( "inN1", "c", ), network.Parameter( "n1", "ramp[0].y" ) ), + network.Connection( network.Parameter( "inN1", "c.g", ), network.Parameter( "n1", "ramp[2].y.b" ) ) ] ) - n1["parameters"]["spline"]["p1"]["x"].setInput( inN1["out"]["c"]["g"] ) + n1["parameters"]["ramp"]["p1"]["x"].setInput( inN1["out"]["c"]["g"] ) - with self.assertRaisesRegex( RuntimeError, "n1.__outAttributes : Shader connections to n1.parameters.spline.p1.x are not supported." ) : + with self.assertRaisesRegex( RuntimeError, "n1.__outAttributes : Shader connections to n1.parameters.ramp.p1.x are not supported." ) : network = n1.attributes()["test:surface"] - n1["parameters"]["spline"]["p1"]["x"].setInput( None ) + n1["parameters"]["ramp"]["p1"]["x"].setInput( None ) - n1["parameters"]["spline"]["interpolation"].setValue( Gaffer.SplineDefinitionInterpolation.Linear ) + n1["parameters"]["ramp"]["interpolation"].setValue( IECore.RampInterpolation.Linear ) network = n1.attributes()["test:surface"] self.assertEqual( network.inputConnections( "n1" ), [ - network.Connection( network.Parameter( "inN1", "c", ), network.Parameter( "n1", "spline[0].y" ) ), - network.Connection( network.Parameter( "inN1", "c.g", ), network.Parameter( "n1", "spline[2].y.b" ) ) + network.Connection( network.Parameter( "inN1", "c", ), network.Parameter( "n1", "ramp[0].y" ) ), + network.Connection( network.Parameter( "inN1", "c.g", ), network.Parameter( "n1", "ramp[2].y.b" ) ) ] ) - n1["parameters"]["spline"]["interpolation"].setValue( Gaffer.SplineDefinitionInterpolation.MonotoneCubic ) - - with self.assertRaisesRegex( RuntimeError, "n1.__outAttributes : Cannot support monotone cubic interpolation for splines with inputs, for plug n1.parameters.spline" ): - network = n1.attributes()["test:surface"] + n1["parameters"]["ramp"]["interpolation"].setValue( IECore.RampInterpolation.MonotoneCubic ) + network = n1.attributes()["test:surface"] def testOptionalParameter( self ) : diff --git a/python/GafferSceneUI/AttributeVisualiserUI.py b/python/GafferSceneUI/AttributeVisualiserUI.py index ac8ef51680..1d6176e3bc 100644 --- a/python/GafferSceneUI/AttributeVisualiserUI.py +++ b/python/GafferSceneUI/AttributeVisualiserUI.py @@ -98,7 +98,7 @@ "description" : """ Used in the Color and False Color modes to define the value which is mapped - to black or the left end of the spline respectively. + to black or the left end of the ramp respectively. """, "layout:activator" : "modeIsColorOrFalseColor", @@ -110,7 +110,7 @@ "description" : """ Used in the Color and False Color modes to define the value which is mapped - to white or the right end of the spline respectively. + to white or the right end of the ramp respectively. """, "layout:activator" : "modeIsColorOrFalseColor", diff --git a/python/GafferSceneUI/CameraQueryUI.py b/python/GafferSceneUI/CameraQueryUI.py index bf79bc60cc..875e50ffa4 100644 --- a/python/GafferSceneUI/CameraQueryUI.py +++ b/python/GafferSceneUI/CameraQueryUI.py @@ -388,8 +388,8 @@ def __menuDefinition( self ) : dataType = IECore.FloatData else : dataType = IECore.DataTraits.dataTypeFromElementType( valueType ) - ## \todo Support Splineff in PlugAlgo::createPlugFromData() - if isinstance( value, IECore.Splineff ) : + ## \todo Support Rampff in PlugAlgo::createPlugFromData() + if isinstance( value, IECore.Rampff ) : plugCreator = functools.partial( Gaffer.ObjectPlug, defaultValue = IECore.NullObject.defaultNullObject() ) else : plugCreator = functools.partial( diff --git a/python/GafferTest/CollectTest.py b/python/GafferTest/CollectTest.py index 47bc8c4883..616aec3e3c 100644 --- a/python/GafferTest/CollectTest.py +++ b/python/GafferTest/CollectTest.py @@ -87,7 +87,7 @@ def testAddInput( self ) : for unsupportedPlug in [ Gaffer.NameValuePlug(), - Gaffer.SplineffPlug( defaultValue = Gaffer.SplineDefinitionff() ), + Gaffer.RampffPlug( defaultValue = IECore.Rampff() ), ] : with self.subTest( inputPlugType = type( unsupportedPlug ) ) : self.assertFalse( node.canAddInput( unsupportedPlug ) ) diff --git a/python/GafferTest/ExpressionTest.py b/python/GafferTest/ExpressionTest.py index 26b3492fa3..3a078ed9d4 100644 --- a/python/GafferTest/ExpressionTest.py +++ b/python/GafferTest/ExpressionTest.py @@ -1143,13 +1143,13 @@ def testNoDefaultExpressionForUnsupportedPlugs( self ) : s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() s["n"]["user"].addChild( - Gaffer.SplineffPlug( - defaultValue = Gaffer.SplineDefinitionff( + Gaffer.RampffPlug( + defaultValue = IECore.Rampff( ( ( 0, 0 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.Linear + IECore.RampInterpolation.Linear ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) diff --git a/python/GafferTest/ExtensionAlgoTest.py b/python/GafferTest/ExtensionAlgoTest.py index 889cb320f8..30492ccfd3 100644 --- a/python/GafferTest/ExtensionAlgoTest.py +++ b/python/GafferTest/ExtensionAlgoTest.py @@ -113,7 +113,7 @@ def testPlugTypes( self ) : box["v2i"] = Gaffer.V2iPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) box["v3i"] = Gaffer.V3iPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) box["color4f"] = Gaffer.Color4fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - box["spline"] = Gaffer.SplinefColor3fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + box["ramp"] = Gaffer.RampfColor3fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) Gaffer.ExtensionAlgo.exportExtension( "PlugTypesExtension", [ box ], self.temporaryDirectory() ) sys.path.append( str( self.temporaryDirectory() / "python" ) ) diff --git a/python/GafferTest/PlugAlgoTest.py b/python/GafferTest/PlugAlgoTest.py index 648e8761b0..120c043439 100644 --- a/python/GafferTest/PlugAlgoTest.py +++ b/python/GafferTest/PlugAlgoTest.py @@ -704,16 +704,16 @@ def testGetValueAsData( self ) : ) n.addChild( Gaffer.FloatVectorDataPlug( "floatVectorPlug", defaultValue = IECore.FloatVectorData( [ 1.0, 2.0, 3.0 ] ) ) ) n.addChild( Gaffer.Box2iPlug( "box2iPlug", defaultValue = imath.Box2i( imath.V2i( 1.0 ), imath.V2i( 2.0 ) ) ) ) - s = Gaffer.SplineDefinitionff( + s = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - n.addChild( Gaffer.SplineffPlug( "splinePlug", defaultValue = s ) ) + n.addChild( Gaffer.RampffPlug( "rampPlug", defaultValue = s ) ) n.addChild( Gaffer.PathMatcherDataPlug( "pathMatcherPlug", defaultValue = IECore.PathMatcherData( IECore.PathMatcher( [ "/test/path", "/test/path2" ] ) ) ) ) self.assertEqual( Gaffer.PlugAlgo.getValueAsData( n["floatPlug"] ), IECore.FloatData( 2.0 ) ) @@ -723,7 +723,7 @@ def testGetValueAsData( self ) : ) self.assertEqual( Gaffer.PlugAlgo.getValueAsData( n["floatVectorPlug"] ), IECore.FloatVectorData( [ 1.0, 2.0, 3.0 ] ) ) self.assertEqual( Gaffer.PlugAlgo.getValueAsData( n["box2iPlug"] ), IECore.Box2iData( imath.Box2i( imath.V2i( 1.0 ), imath.V2i( 2.0 ) ) ) ) - self.assertEqual( Gaffer.PlugAlgo.getValueAsData( n["splinePlug"] ), IECore.SplineffData( s.spline() ) ) + self.assertEqual( Gaffer.PlugAlgo.getValueAsData( n["rampPlug"] ), IECore.RampffData( s ) ) self.assertEqual( Gaffer.PlugAlgo.getValueAsData( n["pathMatcherPlug"] ), IECore.PathMatcherData( IECore.PathMatcher( [ "/test/path", "/test/path2" ] ) ) ) diff --git a/python/GafferTest/SplinePlugTest.py b/python/GafferTest/RampPlugTest.py similarity index 66% rename from python/GafferTest/SplinePlugTest.py rename to python/GafferTest/RampPlugTest.py index 2426148090..b705508474 100644 --- a/python/GafferTest/SplinePlugTest.py +++ b/python/GafferTest/RampPlugTest.py @@ -42,69 +42,25 @@ import Gaffer import GafferTest -class SplinePlugTest( GafferTest.TestCase ) : - - def testSplineDefinition( self ) : - # trimEndPoints now removes any duplicates, regardless of what the interpolation type is - - d = Gaffer.SplineDefinitionff( ((0, 0), (0,0), (0,0), (1,1), (1,1), (1,1)), Gaffer.SplineDefinitionInterpolation.Linear ) - self.assertEqual( d.points(), ((0, 0), (0,0), (0,0), (1,1), (1,1), (1,1)) ) - self.assertEqual( d.interpolation, Gaffer.SplineDefinitionInterpolation.Linear ) - self.assertTrue( d.trimEndPoints() ) - self.assertEqual( d.points(), ((0,0), (1,1)) ) - - d = Gaffer.SplineDefinitionff( ((0, 0), (0,0), (0,0), (1,1), (1,1), (1,1)), Gaffer.SplineDefinitionInterpolation.CatmullRom ) - self.assertEqual( d.points(), ((0, 0), (0,0), (0,0), (1,1), (1,1), (1,1)) ) - self.assertEqual( d.interpolation, Gaffer.SplineDefinitionInterpolation.CatmullRom ) - self.assertTrue( d.trimEndPoints() ) - self.assertEqual( d.points(), ((0, 0), (1,1)) ) - - d = Gaffer.SplineDefinitionff( ((0, 0), (0,0), (0,0), (1,1), (1,1), (1,1)), Gaffer.SplineDefinitionInterpolation.BSpline ) - self.assertEqual( d.points(), ((0, 0), (0,0), (0,0), (1,1), (1,1), (1,1)) ) - self.assertEqual( d.interpolation, Gaffer.SplineDefinitionInterpolation.BSpline ) - self.assertTrue( d.trimEndPoints() ) - self.assertEqual( d.points(), ((0, 0), (1,1)) ) - - d = Gaffer.SplineDefinitionff( ((0, 0), (0,0), (0,0), (1,1), (1,1), (1,1)), Gaffer.SplineDefinitionInterpolation.MonotoneCubic ) - self.assertEqual( d.points(), ((0, 0), (0,0), (0,0), (1,1), (1,1), (1,1)) ) - self.assertEqual( d.interpolation, Gaffer.SplineDefinitionInterpolation.MonotoneCubic ) - self.assertTrue( d.trimEndPoints() ) - self.assertEqual( d.points(), ((0, 0), (1,1)) ) - - - # The only time it doesn't remove duplicates is if there are no duplicates - d = Gaffer.SplineDefinitionff( ((0, 0), (0.5,0.5), (1,1), (1.5,1.5)), Gaffer.SplineDefinitionInterpolation.BSpline ) - self.assertTrue( d.trimEndPoints() ) - self.assertEqual( d.points(), ((0, 0), (0.5,0.5), (1,1), (1.5,1.5)) ) - - - # We trim anything with matching X values, even if the Y-values differ - d = Gaffer.SplineDefinitionff( ((0, 0), (0,0), (0,0), (1,1), (1,1), (1,1.1)), Gaffer.SplineDefinitionInterpolation.BSpline ) - self.assertTrue( d.trimEndPoints() ) - self.assertEqual( d.points(), ((0, 0), (1,1) ) ) - - # We stop trimming as soon as we find anything with a different X value - d = Gaffer.SplineDefinitionff( ((0, 0), (0,0), (0,0), (1,1), (1,1), (1.25,1)), Gaffer.SplineDefinitionInterpolation.BSpline ) - self.assertTrue( d.trimEndPoints() ) - self.assertEqual( d.points(), ((0, 0), (1,1), (1,1), (1.25, 1 )) ) +class RampPlugTest( GafferTest.TestCase ) : def testConstructor( self ) : - s = Gaffer.SplineDefinitionff( + s = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - p = Gaffer.SplineffPlug( "a", defaultValue=s ) + p = Gaffer.RampffPlug( "a", defaultValue=s ) self.assertEqual( p.getValue(), s ) - s2 = Gaffer.SplineDefinitionff( + s2 = IECore.Rampff( ( ( 1, 1 ), ( 1, 1 ), @@ -113,7 +69,7 @@ def testConstructor( self ) : ( 0, 0 ), ( 0, 0 ), ), - Gaffer.SplineDefinitionInterpolation.Linear + IECore.RampInterpolation.Linear ) p.setValue( s2 ) @@ -122,17 +78,17 @@ def testConstructor( self ) : def testSerialisation( self ) : - s = Gaffer.SplineDefinitionff( + s = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - p = Gaffer.SplineffPlug( "a", defaultValue=s, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + p = Gaffer.RampffPlug( "a", defaultValue=s, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) self.assertEqual( p.getValue(), s ) sn = Gaffer.ScriptNode() @@ -149,28 +105,28 @@ def testSerialisation( self ) : def testSerialisationWithNonDefaultValue( self ) : - defaultSpline = Gaffer.SplineDefinitionff( + defaultSpline = IECore.Rampff( ( ( 0, 0 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) sn = Gaffer.ScriptNode() sn["n"] = Gaffer.Node() - sn["n"]["p"] = Gaffer.SplineffPlug( "a", defaultValue=defaultSpline, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + sn["n"]["p"] = Gaffer.RampffPlug( "a", defaultValue=defaultSpline, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) self.assertEqual( sn["n"]["p"].getValue(), defaultSpline ) - valueSpline = Gaffer.SplineDefinitionff( + valueSpline = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) sn["n"]["p"].setValue( valueSpline ) @@ -185,16 +141,16 @@ def testSerialisationWithNonDefaultValue( self ) : def testPointAccess( self ) : - s = Gaffer.SplineDefinitionff( + s = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - p = Gaffer.SplineffPlug( "a", defaultValue=s, flags=Gaffer.Plug.Flags.Dynamic ) + p = Gaffer.RampffPlug( "a", defaultValue=s, flags=Gaffer.Plug.Flags.Dynamic ) self.assertEqual( p.numPoints(), 4 ) for i in range( p.numPoints() ) : @@ -210,16 +166,16 @@ def testPointAccess( self ) : def testPointDeletion( self ) : - s = Gaffer.SplineDefinitionff( + s = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - p = Gaffer.SplineffPlug( "a", defaultValue=s, flags=Gaffer.Plug.Flags.Dynamic ) + p = Gaffer.RampffPlug( "a", defaultValue=s, flags=Gaffer.Plug.Flags.Dynamic ) self.assertEqual( p.numPoints(), 4 ) for i in range( p.numPoints() ) : @@ -245,16 +201,16 @@ def testPointDeletion( self ) : def testPointTampering( self ) : - s = Gaffer.SplineDefinitionff( + s = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - p = Gaffer.SplineffPlug( "a", defaultValue=s, flags=Gaffer.Plug.Flags.Dynamic ) + p = Gaffer.RampffPlug( "a", defaultValue=s, flags=Gaffer.Plug.Flags.Dynamic ) del p.pointPlug( 0 )["x"] del p.pointPlug( 0 )["y"] @@ -264,16 +220,16 @@ def testPointTampering( self ) : def testPlugSetSignal( self ) : - s = Gaffer.SplineDefinitionff( + s = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - p = Gaffer.SplineffPlug( "a", defaultValue=s, flags=Gaffer.Plug.Flags.Dynamic ) + p = Gaffer.RampffPlug( "a", defaultValue=s, flags=Gaffer.Plug.Flags.Dynamic ) n = Gaffer.Node() n["p"] = p @@ -299,25 +255,25 @@ def plugSet( plug ) : def testDefaultValue( self ) : - s1 = Gaffer.SplineDefinitionff( + s1 = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - s2 = Gaffer.SplineDefinitionff( + s2 = IECore.Rampff( ( ( 1, 1 ), ( 0, 0 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - p = Gaffer.SplineffPlug( "a", defaultValue=s1, flags=Gaffer.Plug.Flags.Dynamic ) + p = Gaffer.RampffPlug( "a", defaultValue=s1, flags=Gaffer.Plug.Flags.Dynamic ) self.assertEqual( p.defaultValue(), s1 ) self.assertEqual( p.getValue(), s1 ) @@ -339,27 +295,27 @@ def testDefaultValue( self ) : def testResetDefault( self ) : - s1 = Gaffer.SplineDefinitionff( + s1 = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - s2 = Gaffer.SplineDefinitionff( + s2 = IECore.Rampff( ( ( 1, 1 ), ( 0, 0 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) script = Gaffer.ScriptNode() script["n"] = Gaffer.Node() - script["n"]["user"]["p"] = Gaffer.SplineffPlug( "a", defaultValue = s1, flags = Gaffer.Plug.Flags.Dynamic ) + script["n"]["user"]["p"] = Gaffer.RampffPlug( "a", defaultValue = s1, flags = Gaffer.Plug.Flags.Dynamic ) def assertPreconditions() : @@ -389,34 +345,34 @@ def assertPostconditions() : def testPlugFlags( self ) : - s = Gaffer.SplineDefinitionff( + s = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - p = Gaffer.SplineffPlug( "a", defaultValue=s ) + p = Gaffer.RampffPlug( "a", defaultValue=s ) self.assertEqual( p.pointXPlug( 0 ).getFlags(), Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) self.assertEqual( p.pointYPlug( 0 ).getFlags(), Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) def testConnection( self ) : - s = Gaffer.SplineDefinitionff( + s = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - p1 = Gaffer.SplineffPlug( defaultValue=s ) - p2 = Gaffer.SplineffPlug( defaultValue=s ) + p1 = Gaffer.RampffPlug( defaultValue=s ) + p2 = Gaffer.RampffPlug( defaultValue=s ) p1.setInput( p2 ) @@ -427,40 +383,40 @@ def testConnection( self ) : def testCreateCounterpart( self ) : - s = Gaffer.SplineDefinitionff( + s = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - p1 = Gaffer.SplineffPlug( defaultValue=s ) + p1 = Gaffer.RampffPlug( defaultValue=s ) p2 = p1.createCounterpart( "p2", Gaffer.Plug.Direction.In ) self.assertEqual( p2.getName(), "p2" ) - self.assertTrue( isinstance( p2, Gaffer.SplineffPlug ) ) + self.assertTrue( isinstance( p2, Gaffer.RampffPlug ) ) self.assertEqual( p2.numPoints(), p1.numPoints() ) self.assertTrue( p2.isSetToDefault() ) self.assertEqual( p2.defaultValue(), p1.defaultValue() ) def testPromoteToBox( self ) : - spline = Gaffer.SplineDefinitionff( + ramp = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() - s["n"]["p"] = Gaffer.SplineffPlug( defaultValue=spline ) + s["n"]["p"] = Gaffer.RampffPlug( defaultValue=ramp ) b = Gaffer.Box.create( s, Gaffer.StandardSet( [ s["n"] ] ) ) p = Gaffer.PlugAlgo.promote( b["n"]["p"] ) @@ -474,19 +430,19 @@ def testPromoteToBox( self ) : def testPromoteToBoxWithExtraPoints( self ) : - spline = Gaffer.SplineDefinitionff( + ramp = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() - s["n"]["p"] = Gaffer.SplineffPlug( defaultValue=spline ) + s["n"]["p"] = Gaffer.RampffPlug( defaultValue=ramp ) i = s["n"]["p"].addPoint() s["n"]["p"][i]["x"].setValue( 0.1 ) s["n"]["p"][i]["y"].setValue( 0.2 ) @@ -503,27 +459,27 @@ def testPromoteToBoxWithExtraPoints( self ) : def testSerialisationWithMorePointsThanDefault( self ) : - s1 = Gaffer.SplineDefinitionff( + s1 = IECore.Rampff( ( ( 0, 0 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - s2 = Gaffer.SplineDefinitionff( + s2 = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() - s["n"]["p"] = Gaffer.SplineffPlug( defaultValue=s1, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + s["n"]["p"] = Gaffer.RampffPlug( defaultValue=s1, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) self.assertEqual( s["n"]["p"].getValue(), s1 ) s["n"]["p"].setValue( s2 ) self.assertEqual( s["n"]["p"].getValue(), s2 ) @@ -536,27 +492,27 @@ def testSerialisationWithMorePointsThanDefault( self ) : def testSerialisationWithLessPointsThanDefault( self ) : - s1 = Gaffer.SplineDefinitionff( + s1 = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - s2 = Gaffer.SplineDefinitionff( + s2 = IECore.Rampff( ( ( 0, 0 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() - s["n"]["p"] = Gaffer.SplineffPlug( defaultValue=s1, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + s["n"]["p"] = Gaffer.RampffPlug( defaultValue=s1, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) self.assertEqual( s["n"]["p"].getValue(), s1 ) s["n"]["p"].setValue( s2 ) self.assertEqual( s["n"]["p"].getValue(), s2 ) @@ -569,32 +525,32 @@ def testSerialisationWithLessPointsThanDefault( self ) : def testDefaultConstructor( self ) : - p = Gaffer.SplineffPlug() + p = Gaffer.RampffPlug() p.getValue() def testTruncatedDefaultValue( self ) : - defaultValue = Gaffer.SplineDefinitionff( + defaultValue = IECore.Rampff( ( ( 0, 0 ), ( 0.5, 0.5 ), ( 0.5, 0.5 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) # This tricky value could fool a naive implementation # of isSetToDefault(). - truncatedDefaultValue = Gaffer.SplineDefinitionff( + truncatedDefaultValue = IECore.Rampff( ( ( 0, 0 ), ( 0.5, 0.5 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - p = Gaffer.SplineffPlug( "a", defaultValue=defaultValue, flags=Gaffer.Plug.Flags.Dynamic ) + p = Gaffer.RampffPlug( "a", defaultValue=defaultValue, flags=Gaffer.Plug.Flags.Dynamic ) p.setValue( truncatedDefaultValue ) self.assertEqual( p.defaultValue(), defaultValue ) @@ -603,20 +559,20 @@ def testTruncatedDefaultValue( self ) : def testConnectionSerialisation( self ) : - s = Gaffer.SplineDefinitionff( + s = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) script = Gaffer.ScriptNode() script["n"] = Gaffer.Node() - script["n"]["user"]["p1"] = Gaffer.SplineffPlug( defaultValue=s, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - script["n"]["user"]["p2"] = Gaffer.SplineffPlug( defaultValue=s, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + script["n"]["user"]["p1"] = Gaffer.RampffPlug( defaultValue=s, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + script["n"]["user"]["p2"] = Gaffer.RampffPlug( defaultValue=s, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) script["n"]["user"]["p2"].setInput( script["n"]["user"]["p1"] ) @@ -636,19 +592,19 @@ def assertConnection( script ) : def testPartialConnectionSerialisation( self ) : - s = Gaffer.SplineDefinitionff( + s = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) script = Gaffer.ScriptNode() script["n"] = Gaffer.Node() - script["n"]["user"]["s"] = Gaffer.SplineffPlug( defaultValue=s, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + script["n"]["user"]["s"] = Gaffer.RampffPlug( defaultValue=s, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) script["n"]["user"]["x"] = Gaffer.FloatPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) script["n"]["user"]["y"] = Gaffer.FloatPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) @@ -680,17 +636,17 @@ def assertConnection( script ) : def testDefaultHash( self ) : - s1 = Gaffer.SplineDefinitionff( + s1 = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - s2 = Gaffer.SplineDefinitionff( + s2 = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), @@ -698,30 +654,30 @@ def testDefaultHash( self ) : ( 0.5, 0.95 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - self.assertEqual( Gaffer.SplineffPlug().defaultHash(), Gaffer.SplineffPlug().defaultHash() ) - self.assertNotEqual( Gaffer.SplineffPlug().defaultHash(), Gaffer.SplineffPlug( defaultValue = s1 ).defaultHash() ) + self.assertEqual( Gaffer.RampffPlug().defaultHash(), Gaffer.RampffPlug().defaultHash() ) + self.assertNotEqual( Gaffer.RampffPlug().defaultHash(), Gaffer.RampffPlug( defaultValue = s1 ).defaultHash() ) - p = Gaffer.SplineffPlug( defaultValue = s1 ) + p = Gaffer.RampffPlug( defaultValue = s1 ) h = p.defaultHash() p.setValue( s2 ) self.assertEqual( p.defaultHash(), h ) def testIsSetToDefaultAndConnections( self ) : - definition = Gaffer.SplineDefinitionff( + definition = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - plug = Gaffer.SplineffPlug( defaultValue = definition ) + plug = Gaffer.RampffPlug( defaultValue = definition ) self.assertTrue( plug.isSetToDefault() ) # Static (not computed) input providing the same value as default. diff --git a/python/GafferTest/ReferenceTest.py b/python/GafferTest/ReferenceTest.py index 5a7514ac1a..0b0f5bd637 100644 --- a/python/GafferTest/ReferenceTest.py +++ b/python/GafferTest/ReferenceTest.py @@ -1527,19 +1527,19 @@ def testSpreadsheetWithMixedDefaultAndValueEdits( self ) : self.assertEqual( script["reference"]["rows"][1]["cells"]["c1"]["value"]["y"].getValue(), 3 ) self.assertEqual( script["reference"]["rows"][1]["cells"]["c1"]["value"]["z"].getValue(), 4 ) - def testSplinePlug( self ) : + def testRampPlug( self ) : - splines = [ - Gaffer.SplineDefinitionff( + ramps = [ + IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ), - Gaffer.SplineDefinitionff( + IECore.Rampff( ( ( 1, 1 ), ( 1, 1 ), @@ -1548,7 +1548,7 @@ def testSplinePlug( self ) : ( 0, 0 ), ( 0, 0 ), ), - Gaffer.SplineDefinitionInterpolation.Linear + IECore.RampInterpolation.Linear ) ] @@ -1561,18 +1561,18 @@ def testSplinePlug( self ) : # On one iteration `defaultValue` has more points, # and on the other iteration `otherValue` has more # points. This is useful for catching bugs because - # SplinePlugs must add plugs to represent points. - defaultValue = splines[i] - otherValue = splines[(i+1)%2] + # RampPlugs must add plugs to represent points. + defaultValue = ramps[i] + otherValue = ramps[(i+1)%2] script = Gaffer.ScriptNode() - # Create Box with SplinePlug + # Create Box with RampPlug script["box"] = Gaffer.Box() - script["box"]["spline"] = Gaffer.SplineffPlug( defaultValue = defaultValue, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + script["box"]["ramp"] = Gaffer.RampffPlug( defaultValue = defaultValue, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) if nonDefaultAtExport : - script["box"]["spline"].setValue( otherValue ) + script["box"]["ramp"].setValue( otherValue ) script["box"].exportForReference( fileName ) # Reference it and check we get what we want @@ -1580,60 +1580,60 @@ def testSplinePlug( self ) : script["reference"] = Gaffer.Reference() script["reference"].load( fileName ) - self.assertEqual( script["reference"]["spline"].getValue(), defaultValue ) - self.assertEqual( script["reference"]["spline"].defaultValue(), defaultValue ) - self.assertTrue( script["reference"]["spline"].isSetToDefault() ) + self.assertEqual( script["reference"]["ramp"].getValue(), defaultValue ) + self.assertEqual( script["reference"]["ramp"].defaultValue(), defaultValue ) + self.assertTrue( script["reference"]["ramp"].isSetToDefault() ) # Set value on reference and save and reload the script, checking that # the newly opened script also has the edited value. - script["reference"]["spline"].setValue( otherValue ) - self.assertEqual( script["reference"]["spline"].getValue(), otherValue ) + script["reference"]["ramp"].setValue( otherValue ) + self.assertEqual( script["reference"]["ramp"].getValue(), otherValue ) script2 = Gaffer.ScriptNode() script2.execute( script.serialise() ) - self.assertEqual( script2["reference"]["spline"].getValue(), otherValue ) - self.assertEqual( script2["reference"]["spline"].defaultValue(), defaultValue ) - self.assertFalse( script2["reference"]["spline"].isSetToDefault() ) + self.assertEqual( script2["reference"]["ramp"].getValue(), otherValue ) + self.assertEqual( script2["reference"]["ramp"].defaultValue(), defaultValue ) + self.assertFalse( script2["reference"]["ramp"].isSetToDefault() ) # Reload the reference, and check we kept the edited value. script["reference"].load( fileName ) - self.assertEqual( script["reference"]["spline"].getValue(), otherValue ) + self.assertEqual( script["reference"]["ramp"].getValue(), otherValue ) # Change default value on box and re-export. - script["box"]["spline"].setValue( otherValue ) - script["box"]["spline"].resetDefault() + script["box"]["ramp"].setValue( otherValue ) + script["box"]["ramp"].resetDefault() script["box"].exportForReference( fileName ) # If the reference doesn't have an edit to the value, # then it should pick up the new value on a reload. - script["reference"]["spline"].setToDefault() - self.assertEqual( script["reference"]["spline"].getValue(), defaultValue ) + script["reference"]["ramp"].setToDefault() + self.assertEqual( script["reference"]["ramp"].getValue(), defaultValue ) script["reference"].load( fileName ) - self.assertEqual( script["reference"]["spline"].getValue(), otherValue ) - self.assertEqual( script["reference"]["spline"].defaultValue(), otherValue ) - self.assertTrue( script["reference"]["spline"].isSetToDefault() ) + self.assertEqual( script["reference"]["ramp"].getValue(), otherValue ) + self.assertEqual( script["reference"]["ramp"].defaultValue(), otherValue ) + self.assertTrue( script["reference"]["ramp"].isSetToDefault() ) - def testSplinePlugUpgradeDefault( self ) : + def testRampPlugUpgradeDefault( self ) : script = Gaffer.ScriptNode() - defaultOne = Gaffer.SplineDefinitionff( + defaultOne = IECore.Rampff( ( ( 0, 0 ), ( 0.2, 0.3 ), ( 0.4, 0.9 ), ( 1, 1 ), ), - Gaffer.SplineDefinitionInterpolation.CatmullRom + IECore.RampInterpolation.CatmullRom ) - defaultTwo = Gaffer.SplineDefinitionff( + defaultTwo = IECore.Rampff( ( ( 1, 1 ), ( 1, 1 ), @@ -1642,48 +1642,48 @@ def testSplinePlugUpgradeDefault( self ) : ( 0, 0 ), ( 0, 0 ), ), - Gaffer.SplineDefinitionInterpolation.Linear + IECore.RampInterpolation.Linear ) fileName = self.temporaryDirectory() / "test.grf" script = Gaffer.ScriptNode() - # Export a box with a spline on it + # Export a box with a ramp on it script["box"] = Gaffer.Box() - script["box"]["spline"] = Gaffer.SplineffPlug( defaultValue = defaultOne, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + script["box"]["ramp"] = Gaffer.RampffPlug( defaultValue = defaultOne, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) script["box"].exportForReference( fileName ) - # Make reference1 at default spline value, reference2 with modified spline value + # Make reference1 at default ramp value, reference2 with modified ramp value script["reference1"] = Gaffer.Reference() script["reference1"].load( fileName ) - self.assertEqual( script["reference1"]["spline"].defaultValue(), script["box"]["spline"].defaultValue() ) - self.assertTrue( script["reference1"]["spline"].isSetToDefault() ) + self.assertEqual( script["reference1"]["ramp"].defaultValue(), script["box"]["ramp"].defaultValue() ) + self.assertTrue( script["reference1"]["ramp"].isSetToDefault() ) script["reference2"] = Gaffer.Reference() script["reference2"].load( fileName ) - self.assertEqual( script["reference2"]["spline"].defaultValue(), script["box"]["spline"].defaultValue() ) - self.assertTrue( script["reference2"]["spline"].isSetToDefault() ) - script["reference2"]["spline"].pointPlug( 0 )["y"].setValue( 100 ) - self.assertFalse( script["reference2"]["spline"].isSetToDefault() ) - reference2Value = script["reference2"]["spline"].getValue() + self.assertEqual( script["reference2"]["ramp"].defaultValue(), script["box"]["ramp"].defaultValue() ) + self.assertTrue( script["reference2"]["ramp"].isSetToDefault() ) + script["reference2"]["ramp"].pointPlug( 0 )["y"].setValue( 100 ) + self.assertFalse( script["reference2"]["ramp"].isSetToDefault() ) + reference2Value = script["reference2"]["ramp"].getValue() # Export a new version with a different default. This should # be inherited by reference1 and overridden by reference2. - script["box"]["spline"].setValue( defaultTwo ) - script["box"]["spline"].resetDefault() + script["box"]["ramp"].setValue( defaultTwo ) + script["box"]["ramp"].resetDefault() script["box"].exportForReference( fileName ) script["reference1"].load( fileName ) - self.assertEqual( script["reference1"]["spline"].defaultValue(), script["box"]["spline"].defaultValue() ) - self.assertTrue( script["reference1"]["spline"].isSetToDefault() ) + self.assertEqual( script["reference1"]["ramp"].defaultValue(), script["box"]["ramp"].defaultValue() ) + self.assertTrue( script["reference1"]["ramp"].isSetToDefault() ) script["reference2"].load( fileName ) - self.assertEqual( script["reference2"]["spline"].defaultValue(), script["box"]["spline"].defaultValue() ) - self.assertFalse( script["reference2"]["spline"].isSetToDefault() ) - self.assertEqual( script["reference2"]["spline"].getValue(), reference2Value ) + self.assertEqual( script["reference2"]["ramp"].defaultValue(), script["box"]["ramp"].defaultValue() ) + self.assertFalse( script["reference2"]["ramp"].isSetToDefault() ) + self.assertEqual( script["reference2"]["ramp"].getValue(), reference2Value ) def testAddingChildPlugs( self ) : diff --git a/python/GafferTest/TestCase.py b/python/GafferTest/TestCase.py index 5d60a5eab5..c4b29e8359 100644 --- a/python/GafferTest/TestCase.py +++ b/python/GafferTest/TestCase.py @@ -303,7 +303,7 @@ def __undocumentedPlugs( self, node, additionalTerminalPlugTypes = () ) : Gaffer.V2fPlug, Gaffer.V3fPlug, Gaffer.V2iPlug, Gaffer.V3iPlug, Gaffer.Color3fPlug, Gaffer.Color4fPlug, - Gaffer.SplineffPlug, Gaffer.SplinefColor3fPlug, Gaffer.SplinefColor4fPlug, + Gaffer.RampffPlug, Gaffer.RampfColor3fPlug, Gaffer.RampfColor4fPlug, Gaffer.Box2iPlug, Gaffer.Box3iPlug, Gaffer.Box2fPlug, Gaffer.Box3fPlug, Gaffer.TransformPlug, Gaffer.Transform2DPlug, diff --git a/python/GafferTest/__init__.py b/python/GafferTest/__init__.py index ccabca13cf..f95b095431 100644 --- a/python/GafferTest/__init__.py +++ b/python/GafferTest/__init__.py @@ -83,7 +83,7 @@ def inCI( platforms = set() ) : from .CompoundNumericNode import CompoundNumericNode from .CompoundPlugNode import CompoundPlugNode from .TypedObjectPlugTest import TypedObjectPlugTest -from .SplinePlugTest import SplinePlugTest +from .RampPlugTest import RampPlugTest from .AboutTest import AboutTest from .ChildSetTest import ChildSetTest from .PythonApplicationTest import PythonApplicationTest diff --git a/python/GafferUI/ColorSwatchPlugValueWidget.py b/python/GafferUI/ColorSwatchPlugValueWidget.py index 10d0ea6de4..ad86ae1c1b 100644 --- a/python/GafferUI/ColorSwatchPlugValueWidget.py +++ b/python/GafferUI/ColorSwatchPlugValueWidget.py @@ -134,7 +134,7 @@ def _colorFromPlugs( plugs ) : ## \todo Perhaps we could make this a part of the public API? Perhaps we could also make a # PlugValueDialogue base class to share some of the work with the dialogue made by the -# SplinePlugValueWidget. Or perhaps the `acquire()` here and `NodeSetEditor.acquire()` should +# RampPlugValueWidget. Or perhaps the `acquire()` here and `NodeSetEditor.acquire()` should # actually be functionality of CompoundEditor? class _ColorPlugValueDialogue( GafferUI.ColorChooserDialogue ) : diff --git a/python/GafferUI/RampPlugValueWidget.py b/python/GafferUI/RampPlugValueWidget.py index 13c4584765..a0feb542de 100644 --- a/python/GafferUI/RampPlugValueWidget.py +++ b/python/GafferUI/RampPlugValueWidget.py @@ -1,6 +1,7 @@ ########################################################################## # -# Copyright (c) 2013, Image Engine Design Inc. All rights reserved. +# Copyright (c) 2011-2012, John Haddon. All rights reserved. +# Copyright (c) 2011-2013, Image Engine Design Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -34,16 +35,117 @@ # ########################################################################## -import Gaffer -import GafferUI import imath import IECore -from Qt import QtCore -from Qt import QtGui +import Gaffer +import GafferUI class RampPlugValueWidget( GafferUI.PlugValueWidget ) : + def __init__( self, plug, **kw ) : + + self.__rampWidget = GafferUI.RampWidget() + + GafferUI.PlugValueWidget.__init__( self, self.__rampWidget, plug, **kw ) + + self.__rampWidget._qtWidget().setFixedHeight( 20 ) + + self.buttonPressSignal().connect( Gaffer.WeakMethod( self.__buttonPress ) ) + + self.__editorWindow = None + + self.setPlug( plug ) + + def setPlug( self, plug ) : + + GafferUI.PlugValueWidget.setPlug( self, plug ) + + if isinstance( plug, ( Gaffer.RampfColor3fPlug, Gaffer.RampfColor4fPlug ) ) : + self.__rampWidget.setDrawMode( GafferUI.RampWidget.DrawMode.Ramp ) + else : + self.__rampWidget.setDrawMode( GafferUI.RampWidget.DrawMode.Splines ) + + def setHighlighted( self, highlighted ) : + + GafferUI.PlugValueWidget.setHighlighted( self, highlighted ) + + self.__rampWidget.setHighlighted( highlighted ) + + def _updateFromValues( self, values, exception ) : + + if values : + assert( len( values ) == 1 ) + self.__rampWidget.setRamp( values[0] ) + else : + self.__rampWidget.setRamp( + IECore.Rampff( [ ( 0, 0.3 ), ( 1, 0.3 ) ], IECore.RampInterpolation.Linear ), + ) + + def __buttonPress( self, button, event ) : + + if event.buttons & event.Buttons.Left : + + _RampPlugValueDialogue.acquire( self.getPlug() ) + return True + +for plugType in ( Gaffer.RampffPlug, Gaffer.RampfColor3fPlug, Gaffer.RampfColor4fPlug ) : + + GafferUI.PlugValueWidget.registerType( plugType, RampPlugValueWidget ) + Gaffer.Metadata.registerValue( plugType, "interpolation", "plugValueWidget:type", "GafferUI.PresetsPlugValueWidget" ) + for name, value in sorted( IECore.RampInterpolation.names.items() ): + Gaffer.Metadata.registerValue( plugType, "interpolation", "preset:" + name, value ) + Gaffer.Metadata.registerValue( plugType, "p[0-9]*.x", "labelPlugValueWidget:showValueChangedIndicator", False ) + Gaffer.Metadata.registerValue( plugType, "p[0-9]*.y", "labelPlugValueWidget:showValueChangedIndicator", False ) + +## \todo See comments for `ColorSwatchPlugValueWidget._ColorPlugValueDialogue`. +# I think the best approach is probably to move the `acquire()` mechanism to the +# main layout class when we do an overhaul of that system. +class _RampPlugValueDialogue( GafferUI.Dialogue ) : + + def __init__( self, plug ) : + + GafferUI.Dialogue.__init__( + self, + plug.relativeName( plug.ancestor( Gaffer.ScriptNode ) ) + ) + + self.__plug = plug + self.setChild( _RampPlugEditValueWidget( plug ) ) + + ## \todo Perhaps if `acquire()` were to be a shared central + # mechanism, this handling should be done in `acquire()` + # instead of in each of the individual dialogues? Perhaps + # `acquire()` should even be responsible for building the + # dialogues, so it's able to build a dialogue around any + # PlugValueWidget? + plug.parentChangedSignal().connect( Gaffer.WeakMethod( self.__destroy ) ) + plug.node().parentChangedSignal().connect( Gaffer.WeakMethod( self.__destroy ) ) + + @classmethod + def acquire( cls, plug ) : + + script = plug.node().scriptNode() + scriptWindow = GafferUI.ScriptWindow.acquire( script ) + + for window in scriptWindow.childWindows() : + if isinstance( window, cls ) and window.__plug == plug : + window.setVisible( True ) + return window + + window = cls( plug ) + scriptWindow.addChildWindow( window, removeOnClose = True ) + window.setVisible( True ) + + return window + + def __destroy( self, *unused ) : + + self.parent().removeChild( self ) + +# Private widget class that we open in a popup window when we need to edit a ramp. +class _RampPlugEditValueWidget( GafferUI.PlugValueWidget ) : + def __init__( self, plug, **kw ) : column = GafferUI.ListContainer( GafferUI.ListContainer.Orientation.Vertical, spacing = 4 ) @@ -62,12 +164,12 @@ def __init__( self, plug, **kw ) : GafferUI.Spacer( imath.V2i( 0 ), parenting = { "expand" : True } ) GafferUI.PlugWidget( GafferUI.PlugValueWidget.create( plug["interpolation"] ) ) - self.__splineWidget = GafferUI.SplineWidget() - if isinstance( plug, ( Gaffer.SplinefColor3fPlug, Gaffer.SplinefColor4fPlug ) ) : - self.__splineWidget.setDrawMode( self.__splineWidget.DrawMode.Ramp ) + self.__rampWidget = GafferUI.RampWidget() + if isinstance( plug, ( Gaffer.RampfColor3fPlug, Gaffer.RampfColor4fPlug ) ) : + self.__rampWidget.setDrawMode( self.__rampWidget.DrawMode.Ramp ) else: - self.__splineWidget.setDrawMode( self.__splineWidget.DrawMode.Splines ) - self.__splineWidget._qtWidget().setMinimumHeight( 50 ) + self.__rampWidget.setDrawMode( self.__rampWidget.DrawMode.Splines ) + self.__rampWidget._qtWidget().setMinimumHeight( 50 ) self.__slider = GafferUI.Slider() self.__slider.setMinimumSize( 2 ) @@ -112,7 +214,7 @@ def __init__( self, plug, **kw ) : def __drawModeChanged( self, drawModeWidget ) : name = drawModeWidget.getSelection()[0] - self.__splineWidget.setDrawMode( self.__splineWidget.DrawMode.Ramp if name == "Ramp" else self.__splineWidget.DrawMode.Splines ) + self.__rampWidget.setDrawMode( self.__rampWidget.DrawMode.Ramp if name == "Ramp" else self.__rampWidget.DrawMode.Splines ) def setPlug( self, plug ) : @@ -140,7 +242,7 @@ def _valuesForUpdate( plugs, auxiliaryPlugs ) : return [ { - "spline" : p.getValue().spline(), + "ramp" : p.getValue(), # We can't get these positions from `spline`, because we need # them to have the same order as the point plugs. "positions" : [ p.pointXPlug( i ).getValue() for i in range( 0, p.numPoints() ) ], @@ -152,7 +254,7 @@ def _updateFromValues( self, values, exception ) : assert( len( values ) < 2 ) if len( values ) : - self.__splineWidget.setSpline( values[0]["spline"] ) + self.__rampWidget.setRamp( values[0]["ramp"] ) with Gaffer.Signals.BlockedConnection( self.__positionsChangedConnection ) : self.__slider.setValues( values[0]["positions"] ) @@ -195,11 +297,11 @@ def __positionsChanged( self, slider, reason ) : # on an empty area of the slider. numPoints = plug.numPoints() assert( len( slider.getValues() ) == numPoints + 1 ) - spline = plug.getValue().spline() + evaluator = plug.getValue().evaluator() position = slider.getValues()[numPoints] plug.addPoint() plug.pointXPlug( numPoints ).setValue( position ) - plug.pointYPlug( numPoints ).setValue( spline( position ) ) + plug.pointYPlug( numPoints ).setValue( evaluator( position ) ) def __indexRemoved( self, slider, index ) : @@ -224,9 +326,3 @@ def __selectedIndexChanged( self, slider ) : self.__positionLabel.label().setText( "Position" ) self.__valueLabel.label().setText( "Value" ) - -# we don't register this automatically for any plugs, as it takes up a lot of room -# in the node editor. this means the SplinePlugValueWidget will be used instead, and -# that will launch a dialogue containing a RampPlugValueWidget when appropriate. for -# nodes which want a large editor directly in the node editor, the RampPlugValueWidget -# can be registered directly for specific plugs. diff --git a/python/GafferUI/SplineWidget.py b/python/GafferUI/RampWidget.py similarity index 90% rename from python/GafferUI/SplineWidget.py rename to python/GafferUI/RampWidget.py index 6f57a6c826..b889339753 100644 --- a/python/GafferUI/SplineWidget.py +++ b/python/GafferUI/RampWidget.py @@ -48,12 +48,12 @@ from Qt import QtGui from Qt import QtWidgets -## This Widget simply displays an IECore.Spline object. -class SplineWidget( GafferUI.Widget ) : +## This Widget simply displays an IECore.Ramp object. +class RampWidget( GafferUI.Widget ) : DrawMode = enum.Enum( "DrawMode", [ "Invalid", "Ramp", "Splines" ] ) - def __init__( self, spline=None, drawMode=DrawMode.Splines, **kw ) : + def __init__( self, ramp=None, drawMode=DrawMode.Splines, **kw ) : # using QFrame rather than QWidget because it supports computing the contentsRect() based on # the stylesheet. @@ -63,37 +63,37 @@ def __init__( self, spline=None, drawMode=DrawMode.Splines, **kw ) : self.setDrawMode( drawMode ) - if spline==None : - spline = IECore.Splineff( - IECore.CubicBasisf.catmullRom(), - ( + if ramp == None : + ramp = IECore.Rampff( + [ ( 0, 0 ), ( 0, 0 ), ( 1, 1 ), - ( 1, 1 ), - ) + ( 1, 1 ) + ], + IECore.RampInterpolation.CatmullRom, ) - self.setSpline( spline ) + self.setRamp( ramp ) self._qtWidget().paintEvent = Gaffer.WeakMethod( self.__paintEvent ) - def setSpline( self, spline ) : + def setRamp( self, ramp ) : try : - if spline==self.__spline : + if ramp==self.__ramp : return except : pass - self.__spline = spline + self.__ramp = ramp self.__splinesToDraw = None self.__gradientToDraw = None self._qtWidget().update() - def getSpline( self ) : + def getRamp( self ) : - return self.__spline + return self.__ramp def setDrawMode( self, drawMode ) : @@ -132,10 +132,11 @@ def __paintRamp( self, painter ) : self.__gradientToDraw = QtGui.QImage( QtCore.QSize( numStops, 1 ), QtGui.QImage.Format.Format_RGB32 ) displayTransform = self.displayTransform() + evaluator = self.__ramp.evaluator() for i in range( 0, numStops ) : t = float( i + 0.5 ) / numStops - c = self.__spline( t ) + c = evaluator( t ) if isinstance( c, float ) : c = imath.Color3f( c, c, c ) else : @@ -152,20 +153,21 @@ def __paintSplines( self, painter ) : numPoints = 200 if not self.__splinesToDraw : self.__splinesToDraw = [] - if isinstance( self.__spline, IECore.Splineff ) : + evaluator = self.__ramp.evaluator() + if isinstance( self.__ramp, IECore.Rampff ) : spline = IECore.Struct() spline.color = imath.Color3f( 1 ) spline.path = QtGui.QPainterPath() for i in range( 0, numPoints ) : t = float( i ) / ( numPoints - 1 ) - c = self.__spline( t ) + c = evaluator( t ) if i==0 : spline.path.moveTo( t, c ) else : spline.path.lineTo( t, c ) self.__splinesToDraw.append( spline ) else : - for i in range( 0, self.__spline( 0 ).dimensions() ) : + for i in range( 0, self.__ramp.points()[0][1].dimensions() ) : spline = IECore.Struct() if i==3 : spline.color = imath.Color3f( 1 ) @@ -178,7 +180,7 @@ def __paintSplines( self, painter ) : for i in range( 0, numPoints ) : t = float( i ) / ( numPoints - 1 ) - c = self.__spline( t ) + c = evaluator( t ) for j in range( 0, c.dimensions() ) : if i == 0 : self.__splinesToDraw[j].path.moveTo( t, c[j] ) diff --git a/python/GafferUI/SplinePlugValueWidget.py b/python/GafferUI/SplinePlugValueWidget.py deleted file mode 100644 index a41d05c4b8..0000000000 --- a/python/GafferUI/SplinePlugValueWidget.py +++ /dev/null @@ -1,147 +0,0 @@ -########################################################################## -# -# Copyright (c) 2011-2012, John Haddon. All rights reserved. -# Copyright (c) 2011-2013, Image Engine Design Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above -# copyright notice, this list of conditions and the following -# disclaimer. -# -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided with -# the distribution. -# -# * Neither the name of John Haddon nor the names of -# any other contributors to this software may be used to endorse or -# promote products derived from this software without specific prior -# written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -########################################################################## - -import IECore - -import Gaffer -import GafferUI - -class SplinePlugValueWidget( GafferUI.PlugValueWidget ) : - - def __init__( self, plug, **kw ) : - - self.__splineWidget = GafferUI.SplineWidget() - - GafferUI.PlugValueWidget.__init__( self, self.__splineWidget, plug, **kw ) - - self.__splineWidget._qtWidget().setFixedHeight( 20 ) - - self.buttonPressSignal().connect( Gaffer.WeakMethod( self.__buttonPress ) ) - - self.__editorWindow = None - - self.setPlug( plug ) - - def splineWidget( self ) : - - return self.__splineWidget - - def setPlug( self, plug ) : - - GafferUI.PlugValueWidget.setPlug( self, plug ) - - if isinstance( plug, ( Gaffer.SplinefColor3fPlug, Gaffer.SplinefColor4fPlug ) ) : - self.__splineWidget.setDrawMode( GafferUI.SplineWidget.DrawMode.Ramp ) - else : - self.__splineWidget.setDrawMode( GafferUI.SplineWidget.DrawMode.Splines ) - - def setHighlighted( self, highlighted ) : - - GafferUI.PlugValueWidget.setHighlighted( self, highlighted ) - - self.splineWidget().setHighlighted( highlighted ) - - def _updateFromValues( self, values, exception ) : - - if values : - assert( len( values ) == 1 ) - self.__splineWidget.setSpline( values[0].spline() ) - else : - self.__splineWidget.setSpline( - IECore.Splineff( IECore.CubicBasisf.linear(), [ ( 0, 0.3 ), ( 1, 0.3 ) ] ), - ) - - def __buttonPress( self, button, event ) : - - if event.buttons & event.Buttons.Left : - - _SplinePlugValueDialogue.acquire( self.getPlug() ) - return True - -for plugType in ( Gaffer.SplineffPlug, Gaffer.SplinefColor3fPlug, Gaffer.SplinefColor4fPlug ) : - - GafferUI.PlugValueWidget.registerType( plugType, SplinePlugValueWidget ) - Gaffer.Metadata.registerValue( plugType, "interpolation", "plugValueWidget:type", "GafferUI.PresetsPlugValueWidget" ) - for name, value in sorted( Gaffer.SplineDefinitionInterpolation.names.items() ): - Gaffer.Metadata.registerValue( plugType, "interpolation", "preset:" + name, value ) - Gaffer.Metadata.registerValue( plugType, "p[0-9]*.x", "labelPlugValueWidget:showValueChangedIndicator", False ) - Gaffer.Metadata.registerValue( plugType, "p[0-9]*.y", "labelPlugValueWidget:showValueChangedIndicator", False ) - -## \todo See comments for `ColorSwatchPlugValueWidget._ColorPlugValueDialogue`. -# I think the best approach is probably to move the `acquire()` mechanism to the -# main layout class when we do an overhaul of that system. -class _SplinePlugValueDialogue( GafferUI.Dialogue ) : - - def __init__( self, plug ) : - - GafferUI.Dialogue.__init__( - self, - plug.relativeName( plug.ancestor( Gaffer.ScriptNode ) ) - ) - - self.__plug = plug - self.setChild( GafferUI.RampPlugValueWidget( plug ) ) - - ## \todo Perhaps if `acquire()` were to be a shared central - # mechanism, this handling should be done in `acquire()` - # instead of in each of the individual dialogues? Perhaps - # `acquire()` should even be responsible for building the - # dialogues, so it's able to build a dialogue around any - # PlugValueWidget? - plug.parentChangedSignal().connect( Gaffer.WeakMethod( self.__destroy ) ) - plug.node().parentChangedSignal().connect( Gaffer.WeakMethod( self.__destroy ) ) - - @classmethod - def acquire( cls, plug ) : - - script = plug.node().scriptNode() - scriptWindow = GafferUI.ScriptWindow.acquire( script ) - - for window in scriptWindow.childWindows() : - if isinstance( window, cls ) and window.__plug == plug : - window.setVisible( True ) - return window - - window = cls( plug ) - scriptWindow.addChildWindow( window, removeOnClose = True ) - window.setVisible( True ) - - return window - - def __destroy( self, *unused ) : - - self.parent().removeChild( self ) diff --git a/python/GafferUI/_StyleSheet.py b/python/GafferUI/_StyleSheet.py index f4a84c148b..8872fa55f6 100644 --- a/python/GafferUI/_StyleSheet.py +++ b/python/GafferUI/_StyleSheet.py @@ -443,11 +443,11 @@ def styleColor( key ) : margin-right: 4px; } - QWidget[gafferClass="GafferUI.SplineWidget"] { + QWidget[gafferClass="GafferUI.RampWidget"] { border: 1px solid $backgroundDark; } - QWidget[gafferClass="GafferUI.SplineWidget"][gafferHighlighted="true"] { + QWidget[gafferClass="GafferUI.RampWidget"][gafferHighlighted="true"] { border: 1px solid $brightColor; } diff --git a/python/GafferUI/__init__.py b/python/GafferUI/__init__.py index a1c612df7e..502021d715 100644 --- a/python/GafferUI/__init__.py +++ b/python/GafferUI/__init__.py @@ -177,7 +177,7 @@ def __shiboken() : from .ConfirmationDialogue import ConfirmationDialogue from .Divider import Divider from . import _Pointer -from .SplineWidget import SplineWidget +from .RampWidget import RampWidget from .Bookmarks import Bookmarks from . import WidgetAlgo from .CodeWidget import CodeWidget @@ -247,7 +247,6 @@ def __shiboken() : from . import ScriptNodeUI from .RefreshPlugValueWidget import RefreshPlugValueWidget from . import PreferencesUI -from .SplinePlugValueWidget import SplinePlugValueWidget from .RampPlugValueWidget import RampPlugValueWidget from .NodeFinderDialogue import NodeFinderDialogue from .ConnectionPlugValueWidget import ConnectionPlugValueWidget diff --git a/python/IECoreArnoldTest/CameraAlgoTest.py b/python/IECoreArnoldTest/CameraAlgoTest.py index 6db9fda2ec..abec4cf2bc 100644 --- a/python/IECoreArnoldTest/CameraAlgoTest.py +++ b/python/IECoreArnoldTest/CameraAlgoTest.py @@ -285,14 +285,14 @@ def testConvertShutterCurve( self ) : camera = IECoreScene.Camera() camera.setProjection( "perspective" ) - camera.parameters()["shutter_curve"] = IECore.Splineff( - IECore.CubicBasisf.linear(), + camera.parameters()["shutter_curve"] = IECore.Rampff( [ ( 0, -0.1 ), ( 0.25, 1 ), ( 0.75, 1.1 ), ( 1.1, 0 ), ], + IECore.RampInterpolation.Linear ) node = IECoreArnold.NodeAlgo.convert( camera, universe, "camera" ) @@ -303,8 +303,7 @@ def testConvertShutterCurve( self ) : self.assertEqual( arnold.AiArrayGetVec2( curve, 2 ), arnold.AtVector2( 0.75, 1 ) ) self.assertEqual( arnold.AiArrayGetVec2( curve, 3 ), arnold.AtVector2( 1, 0 ) ) - camera.parameters()["shutter_curve"] = IECore.Splineff( - IECore.CubicBasisf.catmullRom(), + camera.parameters()["shutter_curve"] = IECore.Rampff( [ ( 0, 0 ), ( 0, 0 ), @@ -313,6 +312,7 @@ def testConvertShutterCurve( self ) : ( 1, 0 ), ( 1, 0 ), ], + IECore.RampInterpolation.CatmullRom ) node = IECoreArnold.NodeAlgo.convert( camera, universe, "camera" ) @@ -321,7 +321,7 @@ def testConvertShutterCurve( self ) : for i in range( 0, 25 ) : point = arnold.AiArrayGetVec2( curve, i ) self.assertAlmostEqual( - min( camera.parameters()["shutter_curve"].value( point.x ), 1 ), + min( camera.parameters()["shutter_curve"].value.evaluator()( point.x ), 1 ), point.y, delta = 0.0001 ) diff --git a/python/IECoreArnoldTest/RendererTest.py b/python/IECoreArnoldTest/RendererTest.py index 1ffbbab115..1cbccc55ea 100644 --- a/python/IECoreArnoldTest/RendererTest.py +++ b/python/IECoreArnoldTest/RendererTest.py @@ -2259,58 +2259,58 @@ def testOSLShaders( self ) : "osl:shader", { "scale" : 10.0 } ), - "splineHandle" : IECoreScene.Shader( - "Pattern/ColorSpline", + "rampHandle" : IECoreScene.Shader( + "Pattern/ColorRamp", "osl:shader", { - "spline" : IECore.SplinefColor3f( - IECore.CubicBasisf.bSpline(), + "ramp" : IECore.RampfColor3f( [ ( 0, imath.Color3f( 0 ) ), ( 0.25, imath.Color3f( 0.25 ) ), ( 0.5, imath.Color3f( 0.5 ) ), ( 1, imath.Color3f( 1 ) ), - ] + ], + IECore.RampInterpolation.BSpline ), } ), - "floatSplineHandle" : IECoreScene.Shader( - "Pattern/FloatSpline", + "floatRampHandle" : IECoreScene.Shader( + "Pattern/FloatRamp", "osl:shader", { - "spline" : IECore.Splineff( - IECore.CubicBasisf.linear(), + "ramp" : IECore.Rampff( [ ( 0, 0.25 ), ( 1, 0.5 ), - ] + ], + IECore.RampInterpolation.Linear ), } ), - "splineWithInputsHandle" : IECoreScene.Shader( - "Pattern/ColorSpline", + "rampWithInputsHandle" : IECoreScene.Shader( + "Pattern/ColorRamp", "osl:shader", { - "spline" : IECore.SplinefColor3f( - IECore.CubicBasisf.catmullRom(), + "ramp" : IECore.RampfColor3f( [ ( 0, imath.Color3f( 0 ) ), ( 0.25, imath.Color3f( 0.25 ) ), ( 0.5, imath.Color3f( 0.5 ) ), ( 1, imath.Color3f( 1 ) ), - ] + ], + IECore.RampInterpolation.CatmullRom ), } ), "output" : IECoreScene.Shader( "switch_rgba", "ai:surface" ), }, connections = [ - ( ( "splineHandle", "c" ), ( "output", "input1" ) ), + ( ( "rampHandle", "c" ), ( "output", "input1" ) ), ( ( "noiseHandle", "n" ), ( "output", "input2" ) ), - ( ( "floatSplineHandle", "c" ), ( "output", "input3" ) ), - ( ( "splineWithInputsHandle", "c" ), ( "output", "input4" ) ), - ( ( "globalsHandle", "globalP" ), ( "splineWithInputsHandle", "spline[0].y" ) ), - ( ( "globalsHandle", "globalV" ), ( "splineWithInputsHandle", "spline[3].y.g" ) ), + ( ( "floatRampHandle", "c" ), ( "output", "input3" ) ), + ( ( "rampWithInputsHandle", "c" ), ( "output", "input4" ) ), + ( ( "globalsHandle", "globalP" ), ( "rampWithInputsHandle", "ramp[0].y" ) ), + ( ( "globalsHandle", "globalV" ), ( "rampWithInputsHandle", "ramp[3].y.g" ) ), ], output = ( "output", "out" ), ) @@ -2337,69 +2337,88 @@ def testOSLShaders( self ) : switch = arnold.AiNodeGetPtr( n, "shader" ) self.assertEqual( arnold.AiNodeEntryGetName( arnold.AiNodeGetNodeEntry( switch ) ), "switch_rgba" ) - spline = arnold.AiNodeGetLink( switch, "input1" ) - self.assertEqual( arnold.AiNodeEntryGetName( arnold.AiNodeGetNodeEntry( spline ) ), "osl" ) - self.assertEqual( arnold.AiNodeGetStr( spline, "shadername" ), "Pattern/ColorSpline" ) - self.assertEqual( arnold.AiNodeGetStr( spline, "param_splineBasis" ), "bspline" ) - - splinePositions = arnold.AiNodeGetArray( spline, "param_splinePositions" ) - self.assertEqual( arnold.AiArrayGetFlt( splinePositions, 0 ), 0 ) - self.assertEqual( arnold.AiArrayGetFlt( splinePositions, 1 ), 0.25 ) - self.assertEqual( arnold.AiArrayGetFlt( splinePositions, 2 ), 0.5 ) - self.assertEqual( arnold.AiArrayGetFlt( splinePositions, 3 ), 1 ) - - splineValues = arnold.AiNodeGetArray( spline, "param_splineValues" ) - self.assertEqual( arnold.AiArrayGetRGB( splineValues, 0 ), arnold.AtRGB( 0, 0, 0 ) ) - self.assertEqual( arnold.AiArrayGetRGB( splineValues, 1 ), arnold.AtRGB( 0.25, 0.25, 0.25 ) ) - self.assertEqual( arnold.AiArrayGetRGB( splineValues, 2 ), arnold.AtRGB( 0.5, 0.5, 0.5 ) ) - self.assertEqual( arnold.AiArrayGetRGB( splineValues, 3 ), arnold.AtRGB( 1, 1, 1 ) ) - - floatSpline = arnold.AiNodeGetLink( switch, "input3" ) - self.assertEqual( arnold.AiNodeEntryGetName( arnold.AiNodeGetNodeEntry( floatSpline ) ), "osl" ) - self.assertEqual( arnold.AiNodeGetStr( floatSpline, "shadername" ), "Pattern/FloatSpline" ) - self.assertEqual( arnold.AiNodeGetStr( floatSpline, "param_splineBasis" ), "linear" ) - - floatSplinePositions = arnold.AiNodeGetArray( floatSpline, "param_splinePositions" ) - self.assertEqual( arnold.AiArrayGetFlt( floatSplinePositions, 0 ), 0 ) - self.assertEqual( arnold.AiArrayGetFlt( floatSplinePositions, 1 ), 0 ) - self.assertEqual( arnold.AiArrayGetFlt( floatSplinePositions, 2 ), 1 ) - self.assertEqual( arnold.AiArrayGetFlt( floatSplinePositions, 3 ), 1 ) - - floatSplineValues = arnold.AiNodeGetArray( floatSpline, "param_splineValues" ) - self.assertEqual( arnold.AiArrayGetFlt( floatSplineValues, 0 ), 0.25 ) - self.assertEqual( arnold.AiArrayGetFlt( floatSplineValues, 1 ), 0.25 ) - self.assertEqual( arnold.AiArrayGetFlt( floatSplineValues, 2 ), 0.5 ) - self.assertEqual( arnold.AiArrayGetFlt( floatSplineValues, 3 ), 0.5 ) + ramp = arnold.AiNodeGetLink( switch, "input1" ) + self.assertEqual( arnold.AiNodeEntryGetName( arnold.AiNodeGetNodeEntry( ramp ) ), "osl" ) + self.assertEqual( arnold.AiNodeGetStr( ramp, "shadername" ), "Pattern/ColorRamp" ) + self.assertEqual( arnold.AiNodeGetStr( ramp, "param_rampBasis" ), "bspline" ) + + rampPositions = arnold.AiNodeGetArray( ramp, "param_rampPositions" ) + self.assertEqual( arnold.AiArrayGetFlt( rampPositions, 0 ), 0 ) + self.assertEqual( arnold.AiArrayGetFlt( rampPositions, 1 ), 0 ) + self.assertEqual( arnold.AiArrayGetFlt( rampPositions, 2 ), 0 ) + self.assertEqual( arnold.AiArrayGetFlt( rampPositions, 3 ), 0.25 ) + self.assertEqual( arnold.AiArrayGetFlt( rampPositions, 4 ), 0.5 ) + self.assertEqual( arnold.AiArrayGetFlt( rampPositions, 5 ), 1 ) + self.assertEqual( arnold.AiArrayGetFlt( rampPositions, 6 ), 1 ) + self.assertEqual( arnold.AiArrayGetFlt( rampPositions, 7 ), 1 ) + + rampValues = arnold.AiNodeGetArray( ramp, "param_rampValues" ) + self.assertEqual( arnold.AiArrayGetRGB( rampValues, 0 ), arnold.AtRGB( 0, 0, 0 ) ) + self.assertEqual( arnold.AiArrayGetRGB( rampValues, 1 ), arnold.AtRGB( 0, 0, 0 ) ) + self.assertEqual( arnold.AiArrayGetRGB( rampValues, 2 ), arnold.AtRGB( 0, 0, 0 ) ) + self.assertEqual( arnold.AiArrayGetRGB( rampValues, 3 ), arnold.AtRGB( 0.25, 0.25, 0.25 ) ) + self.assertEqual( arnold.AiArrayGetRGB( rampValues, 4 ), arnold.AtRGB( 0.5, 0.5, 0.5 ) ) + self.assertEqual( arnold.AiArrayGetRGB( rampValues, 5 ), arnold.AtRGB( 1, 1, 1 ) ) + self.assertEqual( arnold.AiArrayGetRGB( rampValues, 6 ), arnold.AtRGB( 1, 1, 1 ) ) + self.assertEqual( arnold.AiArrayGetRGB( rampValues, 7 ), arnold.AtRGB( 1, 1, 1 ) ) + + floatRamp = arnold.AiNodeGetLink( switch, "input3" ) + self.assertEqual( arnold.AiNodeEntryGetName( arnold.AiNodeGetNodeEntry( floatRamp ) ), "osl" ) + self.assertEqual( arnold.AiNodeGetStr( floatRamp, "shadername" ), "Pattern/FloatRamp" ) + self.assertEqual( arnold.AiNodeGetStr( floatRamp, "param_rampBasis" ), "linear" ) + + floatRampPositions = arnold.AiNodeGetArray( floatRamp, "param_rampPositions" ) + self.assertEqual( arnold.AiArrayGetFlt( floatRampPositions, 0 ), 0 ) + self.assertEqual( arnold.AiArrayGetFlt( floatRampPositions, 1 ), 0 ) + self.assertEqual( arnold.AiArrayGetFlt( floatRampPositions, 2 ), 1 ) + self.assertEqual( arnold.AiArrayGetFlt( floatRampPositions, 3 ), 1 ) + + floatRampValues = arnold.AiNodeGetArray( floatRamp, "param_rampValues" ) + self.assertEqual( arnold.AiArrayGetFlt( floatRampValues, 0 ), 0.25 ) + self.assertEqual( arnold.AiArrayGetFlt( floatRampValues, 1 ), 0.25 ) + self.assertEqual( arnold.AiArrayGetFlt( floatRampValues, 2 ), 0.5 ) + self.assertEqual( arnold.AiArrayGetFlt( floatRampValues, 3 ), 0.5 ) noise = arnold.AiNodeGetLink( switch, "input2" ) self.assertEqual( arnold.AiNodeEntryGetName( arnold.AiNodeGetNodeEntry( noise ) ), "osl" ) self.assertEqual( arnold.AiNodeGetStr( noise, "shadername" ), "Pattern/Noise" ) self.assertEqual( arnold.AiNodeGetFlt( noise, "param_scale" ), 10.0 ) - splineWithInputs = arnold.AiNodeGetLink( switch, "input4" ) - self.assertEqual( arnold.AiNodeEntryGetName( arnold.AiNodeGetNodeEntry( splineWithInputs ) ), "osl" ) - self.assertEqual( arnold.AiNodeGetStr( splineWithInputs, "shadername" ), "Pattern/ColorSpline" ) - self.assertEqual( arnold.AiNodeGetStr( splineWithInputs, "param_splineBasis" ), "catmull-rom" ) - - splineWithInputsPositions = arnold.AiNodeGetArray( splineWithInputs, "param_splinePositions" ) - self.assertEqual( arnold.AiArrayGetFlt( splineWithInputsPositions, 0 ), 0 ) - self.assertEqual( arnold.AiArrayGetFlt( splineWithInputsPositions, 1 ), 0.25 ) - self.assertEqual( arnold.AiArrayGetFlt( splineWithInputsPositions, 2 ), 0.5 ) - self.assertEqual( arnold.AiArrayGetFlt( splineWithInputsPositions, 3 ), 1 ) - - splineWithInputsAdapter = arnold.AiNodeGetLink( splineWithInputs, "param_splineValues" ) - self.assertEqual( arnold.AiNodeEntryGetName( arnold.AiNodeGetNodeEntry( splineWithInputsAdapter ) ), "osl" ) - self.assertEqual( arnold.AiNodeGetStr( splineWithInputsAdapter, "shadername" ), "Utility/__ColorToArray" ) - self.assertEqual( arnold.AiNodeGetRGB( splineWithInputsAdapter, "param_in1" ), arnold.AtRGB( 0.25, 0.25, 0.25 ) ) - self.assertEqual( arnold.AiNodeGetRGB( splineWithInputsAdapter, "param_in2" ), arnold.AtRGB( 0.5, 0.5, 0.5 ) ) - - globalPInput = arnold.AiNodeGetLink( splineWithInputsAdapter, "param_in0" ) - self.assertEqual( arnold.AiNodeGetStr( globalPInput, "shadername" ), "Utility/Globals" ) - - componentAdapterInput = arnold.AiNodeGetLink( splineWithInputsAdapter, "param_in3" ) - self.assertEqual( arnold.AiNodeGetStr( componentAdapterInput, "shadername" ), "MaterialX/mx_pack_color" ) - globalVInput = arnold.AiNodeGetLink( componentAdapterInput, "param_in2" ) - self.assertEqual( arnold.AiNodeGetStr( globalVInput, "shadername" ), "Utility/Globals" ) + rampWithInputs = arnold.AiNodeGetLink( switch, "input4" ) + self.assertEqual( arnold.AiNodeEntryGetName( arnold.AiNodeGetNodeEntry( rampWithInputs ) ), "osl" ) + self.assertEqual( arnold.AiNodeGetStr( rampWithInputs, "shadername" ), "Pattern/ColorRamp" ) + self.assertEqual( arnold.AiNodeGetStr( rampWithInputs, "param_rampBasis" ), "catmull-rom" ) + + rampWithInputsPositions = arnold.AiNodeGetArray( rampWithInputs, "param_rampPositions" ) + self.assertEqual( arnold.AiArrayGetFlt( rampWithInputsPositions, 0 ), 0 ) + self.assertEqual( arnold.AiArrayGetFlt( rampWithInputsPositions, 1 ), 0 ) + self.assertEqual( arnold.AiArrayGetFlt( rampWithInputsPositions, 2 ), 0.25 ) + self.assertEqual( arnold.AiArrayGetFlt( rampWithInputsPositions, 3 ), 0.5 ) + self.assertEqual( arnold.AiArrayGetFlt( rampWithInputsPositions, 4 ), 1 ) + self.assertEqual( arnold.AiArrayGetFlt( rampWithInputsPositions, 5 ), 1 ) + + rampWithInputsAdapter = arnold.AiNodeGetLink( rampWithInputs, "param_rampValues" ) + self.assertEqual( arnold.AiNodeEntryGetName( arnold.AiNodeGetNodeEntry( rampWithInputsAdapter ) ), "osl" ) + self.assertEqual( arnold.AiNodeGetStr( rampWithInputsAdapter, "shadername" ), "Utility/__ColorToArray" ) + self.assertEqual( arnold.AiNodeGetRGB( rampWithInputsAdapter, "param_in2" ), arnold.AtRGB( 0.25, 0.25, 0.25 ) ) + self.assertEqual( arnold.AiNodeGetRGB( rampWithInputsAdapter, "param_in3" ), arnold.AtRGB( 0.5, 0.5, 0.5 ) ) + + globalPInput0 = arnold.AiNodeGetLink( rampWithInputsAdapter, "param_in0" ) + self.assertEqual( arnold.AiNodeGetStr( globalPInput0, "shadername" ), "Utility/Globals" ) + + globalPInput1 = arnold.AiNodeGetLink( rampWithInputsAdapter, "param_in1" ) + self.assertEqual( arnold.AiNodeGetStr( globalPInput1, "shadername" ), "Utility/Globals" ) + + componentAdapterInput4 = arnold.AiNodeGetLink( rampWithInputsAdapter, "param_in4" ) + self.assertEqual( arnold.AiNodeGetStr( componentAdapterInput4, "shadername" ), "MaterialX/mx_pack_color" ) + globalVInput4 = arnold.AiNodeGetLink( componentAdapterInput4, "param_in2" ) + self.assertEqual( arnold.AiNodeGetStr( globalVInput4, "shadername" ), "Utility/Globals" ) + + componentAdapterInput5 = arnold.AiNodeGetLink( rampWithInputsAdapter, "param_in5" ) + self.assertEqual( arnold.AiNodeGetStr( componentAdapterInput5, "shadername" ), "MaterialX/mx_pack_color" ) + globalVInput5 = arnold.AiNodeGetLink( componentAdapterInput5, "param_in2" ) + self.assertEqual( arnold.AiNodeGetStr( globalVInput5, "shadername" ), "Utility/Globals" ) + def testPureOSLShaders( self ) : diff --git a/python/IECoreDelightTest/RendererTest.py b/python/IECoreDelightTest/RendererTest.py index f7c4aa4289..88a38d923b 100644 --- a/python/IECoreDelightTest/RendererTest.py +++ b/python/IECoreDelightTest/RendererTest.py @@ -963,7 +963,7 @@ def testShaderAttributes( self ) : def test3DelightSplineParameters( self ) : - # Converting from OSL parameters to Gaffer spline parameters is + # Converting from OSL parameters to Gaffer ramp parameters is # tested in GafferOSLTest.OSLShaderTest r = GafferScene.Private.IECoreScenePreview.Renderer.create( @@ -982,59 +982,49 @@ def test3DelightSplineParameters( self ) : s, "osl:shader", { - "floatSpline" : IECore.Splineff( - IECore.CubicBasisf.linear(), + "floatSpline" : IECore.Rampff( [ ( 0, 0.25 ), ( 0, 0.25 ), ( 1, 0.75 ), ( 1, 0.75 ), - ] + ], + IECore.RampInterpolation.Linear ), - "colorSpline" : IECore.SplinefColor3f( - IECore.CubicBasisf.bSpline(), + "colorSpline" : IECore.RampfColor3f( [ ( 0, imath.Color3f( 0.25 ) ), - ( 0, imath.Color3f( 0.25 ) ), - ( 0, imath.Color3f( 0.25 ) ), - ( 1, imath.Color3f( 0.75 ) ), ( 1, imath.Color3f( 0.75 ) ), - ( 1, imath.Color3f( 0.75 ) ), - ] + ], + IECore.RampInterpolation.BSpline ), - "dualInterpolationSpline" : IECore.Splineff( - IECore.CubicBasisf.linear(), + "dualInterpolationSpline" : IECore.Rampff( [ ( 0, 0.25 ), ( 1, 0.75 ), - ] + ], + IECore.RampInterpolation.Linear ), - "trimmedFloatSpline" : IECore.Splineff( - IECore.CubicBasisf.catmullRom(), + "trimmedFloatSpline" : IECore.Rampff( [ ( 0, 0.25 ), - ( 0, 0.25 ), - ( 1, 0.75 ), ( 1, 0.75 ), - ] + ], + IECore.RampInterpolation.CatmullRom ), - "mayaSpline" : IECore.Splineff( - IECore.CubicBasisf.linear(), + "mayaSpline" : IECore.Rampff( [ ( 0, 0.25 ), ( 1, 0.75 ), - ] + ], + IECore.RampInterpolation.Linear ), - "inconsistentNameSpline": IECore.Splineff( - IECore.CubicBasisf.bSpline(), + "inconsistentNameSpline": IECore.Rampff( [ ( 0, 0.25 ), - ( 0, 0.25 ), - ( 0, 0.25 ), - ( 1, 0.75 ), ( 1, 0.75 ), - ( 1, 0.75 ), - ] + ], + IECore.RampInterpolation.BSpline ), } ), @@ -1123,7 +1113,7 @@ def test3DelightSplineParameters( self ) : self.assertNotIn( "inconsistentNameSplineValues", shader ) self.assertNotIn( "inconsistentNameSplineBasis", shader ) - def testGafferSplineParameters( self ) : + def testGafferRampParameters( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", @@ -1133,27 +1123,27 @@ def testGafferSplineParameters( self ) : network = IECoreScene.ShaderNetwork( shaders = { - "splineHandle" : IECoreScene.Shader( - "Pattern/ColorSpline", + "rampHandle" : IECoreScene.Shader( + "Pattern/ColorRamp", "osl:shader", { - "spline" : IECore.SplinefColor3f( - IECore.CubicBasisf.linear(), + "ramp" : IECore.RampfColor3f( [ ( 0, imath.Color3f( 1, 0, 0 ) ), ( 0, imath.Color3f( 1, 0, 0 ) ), ( 1, imath.Color3f( 0, 0, 1 ) ), ( 1, imath.Color3f( 0, 0, 1 ) ), - ] + ], + IECore.RampInterpolation.Linear ), } ), "constHandle" : IECoreScene.Shader( "Surface/Constant", "osl:surface", {} ) }, connections = [ - ( ( "splineHandle", "" ), ( "constHandle", "Cs" ) ), + ( ( "rampHandle", "" ), ( "constHandle", "Cs" ) ), ], - output = "splineHandle" + output = "rampHandle" ) o = r.object( @@ -1172,9 +1162,9 @@ def testGafferSplineParameters( self ) : self.assertEqual( len( shaders ), 1 ) shader = shaders[next( iter( shaders ) )] - self.assertEqual( shader["splinePositions"], [ 0, 0, 0, 1, 1, 1 ] ) + self.assertEqual( shader["rampPositions"], [ 0, 0, 0, 1, 1, 1 ] ) self.assertEqual( - shader["splineValues"], + shader["rampValues"], [ imath.Color3f( 1, 0, 0 ), imath.Color3f( 1, 0, 0 ), @@ -1184,7 +1174,7 @@ def testGafferSplineParameters( self ) : imath.Color3f( 0, 0, 1 ) ] ) - self.assertEqual( shader["splineBasis"], "linear" ) + self.assertEqual( shader["rampBasis"], "linear" ) def testUVCoordShaderInserted( self ) : diff --git a/src/Gaffer/Plug.cpp b/src/Gaffer/Plug.cpp index 5de181e1cd..5a3a597370 100644 --- a/src/Gaffer/Plug.cpp +++ b/src/Gaffer/Plug.cpp @@ -866,7 +866,7 @@ class Plug::DirtyPlugs } else { - // We can end up here when constructing a SplinePlug, + // We can end up here when constructing a RampPlug, // because it calls setValue() in its constructor. // We don't want to increment the reference count on // an in-construction plug, because then we'll destroy diff --git a/src/Gaffer/PlugAlgo.cpp b/src/Gaffer/PlugAlgo.cpp index 6dc8d7bb24..b9809702e8 100644 --- a/src/Gaffer/PlugAlgo.cpp +++ b/src/Gaffer/PlugAlgo.cpp @@ -47,7 +47,7 @@ #include "Gaffer/Node.h" #include "Gaffer/NumericPlug.h" #include "Gaffer/StringPlug.h" -#include "Gaffer/SplinePlug.h" +#include "Gaffer/RampPlug.h" #include "Gaffer/Spreadsheet.h" #include "Gaffer/Switch.h" #include "Gaffer/TransformPlug.h" @@ -55,7 +55,7 @@ #include "Gaffer/ValuePlug.h" #include "IECore/DataAlgo.h" -#include "IECore/SplineData.h" +#include "IECore/RampData.h" #include "boost/algorithm/string/classification.hpp" #include "boost/algorithm/string/join.hpp" @@ -584,10 +584,10 @@ IECore::DataPtr getValueAsData( const ValuePlug *plug ) return static_cast( plug )->getValue()->copy(); case Box2fVectorDataPlugTypeId : return static_cast( plug )->getValue()->copy(); - case SplineffPlugTypeId : - return new SplineffData( static_cast( plug )->getValue().spline() ); - case SplinefColor3fPlugTypeId : - return new SplinefColor3fData( static_cast( plug )->getValue().spline() ); + case RampffPlugTypeId : + return new RampffData( static_cast( plug )->getValue() ); + case RampfColor3fPlugTypeId : + return new RampfColor3fData( static_cast( plug )->getValue() ); case TransformPlugTypeId : return new M44fData( static_cast( plug )->matrix() ); case M44fPlugTypeId : diff --git a/src/Gaffer/RampPlug.cpp b/src/Gaffer/RampPlug.cpp new file mode 100644 index 0000000000..a393b45681 --- /dev/null +++ b/src/Gaffer/RampPlug.cpp @@ -0,0 +1,357 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011-2012, John Haddon. All rights reserved. +// Copyright (c) 2013, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#include "Gaffer/RampPlug.h" + +#include "Gaffer/Action.h" +#include "Gaffer/PlugAlgo.h" + +using namespace Gaffer; + +template +const IECore::RunTimeTyped::TypeDescription > RampPlug::g_typeDescription; + +template +RampPlug::RampPlug( const std::string &name, Direction direction, const ValueType &defaultValue, unsigned flags ) + : ValuePlug( name, direction, flags ), m_defaultValue( defaultValue ) +{ + addChild( new IntPlug( "interpolation", direction, (int)IECore::RampInterpolation::CatmullRom, + (int)IECore::RampInterpolation::Linear, (int)IECore::RampInterpolation::Constant ) ); + + setToDefault(); +} + +template +RampPlug::~RampPlug() +{ +} + +template +bool RampPlug::acceptsChild( const GraphComponent *potentialChild ) const +{ + if( children().size() < 1 ) + { + // to let the interpolation plug through during construction + return true; + } + + const ValuePlug *c = IECore::runTimeCast( potentialChild ); + if( !c ) + { + return false; + } + + if( c->children().size()==0 ) + { + // when we're getting loaded from a serialisation, the point plugs are + // added before the point.x and point.y plugs are added, so we have to + // make this concession. + return true; + } + + if( c->children().size()!=2 ) + { + return false; + } + if( !c->getChild( "x" ) ) + { + return false; + } + if( !c->getChild( "y" ) ) + { + return false; + } + return true; +} + +template +PlugPtr RampPlug::createCounterpart( const std::string &name, Direction direction ) const +{ + Ptr result = new RampPlug( name, direction, m_defaultValue, getFlags() ); + result->clearPoints(); + for( unsigned i = 0; i < numPoints(); ++i ) + { + const ValuePlug *p = pointPlug( i ); + result->addChild( p->createCounterpart( p->getName(), direction ) ); + } + return result; +} + +template +const T &RampPlug::defaultValue() const +{ + return m_defaultValue; +} + +template +void RampPlug::setToDefault() +{ + setValue( m_defaultValue ); + for( const auto &p : ValuePlug::Range( *this ) ) + { + p->resetDefault(); + } +} + +template +void RampPlug::resetDefault() +{ + ValuePlug::resetDefault(); + + const T newDefault = getValue(); + const T oldDefault = m_defaultValue; + Action::enact( + this, + [this, newDefault] () { + this->m_defaultValue = newDefault; + }, + [this, oldDefault] () { + this->m_defaultValue = oldDefault; + } + ); +} + +template +bool RampPlug::isSetToDefault() const +{ + for( const auto &p : ValuePlug::RecursiveRange( *this ) ) + { + if( p->children().empty() && PlugAlgo::dependsOnCompute( p.get() ) ) + { + // Value can vary by context, so there is no single "current value", + // and therefore no true concept of whether or not it's at the default. + return false; + } + } + return getValue() == m_defaultValue; +} + +template +IECore::MurmurHash RampPlug::defaultHash() const +{ + IECore::MurmurHash result; + result.append( typeId() ); + result.append( m_defaultValue.interpolation ); + for( auto &p : m_defaultValue.points ) + { + result.append( p.first ); + result.append( p.second ); + } + return result; +} + +template +void RampPlug::setValue( const T &value ) +{ + interpolationPlug()->setValue( (int)value.interpolation ); + + typename T::PointContainer::const_iterator it = value.points.begin(); + typename T::PointContainer::const_iterator eIt = value.points.end(); + + unsigned existingPoints = numPoints(); + unsigned i = 0; + for( ; it!=eIt; ++it ) + { + if( i >= existingPoints ) + { + addPoint(); + } + pointXPlug( i )->setValue( it->first ); + pointYPlug( i )->setValue( it->second ); + i++; + } + + // remove unneeded preexisting points + while( numPoints() > i ) + { + removeChild( pointPlug( i ) ); + } +} + +template +T RampPlug::getValue() const +{ + T result; + result.interpolation = (IECore::RampInterpolation)interpolationPlug()->getValue(); + + unsigned n = numPoints(); + for( unsigned i=0; igetValue(), pointYPlug( i )->getValue() ) ); + } + + return result; +} + + +template +IntPlug *RampPlug::interpolationPlug() +{ + return getChild( "interpolation" ); +} + +template +const IntPlug *RampPlug::interpolationPlug() const +{ + return getChild( "interpolation" ); +} + +template +unsigned RampPlug::numPoints() const +{ + return children().size() - 1; +} + +template +unsigned RampPlug::addPoint() +{ + const unsigned n = numPoints(); + ValuePlugPtr p = new ValuePlug( "p0", direction() ); + p->setFlags( Plug::Dynamic, true ); + + typename XPlugType::Ptr x = new XPlugType( "x", direction(), typename T::XType( 0 ) ); + x->setFlags( Plug::Dynamic, true ); + p->addChild( x ); + + typename YPlugType::Ptr y = new YPlugType( "y", direction(), typename T::YType( 0 ) ); + y->setFlags( Plug::Dynamic, true ); + p->addChild( y ); + + addChild( p ); + + return n; +} + +template +void RampPlug::removePoint( unsigned pointIndex ) +{ + removeChild( pointPlug( pointIndex ) ); +} + +template +void RampPlug::clearPoints() +{ + unsigned i = numPoints(); + if( !i ) + { + return; + } + + do { + removePoint( --i ); + } while( i!=0 ); +} + +template +ValuePlug *RampPlug::pointPlug( unsigned pointIndex ) +{ + if( pointIndex >= numPoints() ) + { + throw IECore::Exception( "Point index out of range." ); + } + return getChild( pointIndex + 1 ); // plus one is to skip interpolation plug +} + +template +const ValuePlug *RampPlug::pointPlug( unsigned pointIndex ) const +{ + if( pointIndex >= numPoints() ) + { + throw IECore::Exception( "Point index out of range." ); + } + return getChild( pointIndex + 1 ); // plus one is to skip interpolation plug +} + +template +typename RampPlug::XPlugType *RampPlug::pointXPlug( unsigned pointIndex ) +{ + XPlugType *p = pointPlug( pointIndex )->template getChild( "x" ); + if( !p ) + { + throw IECore::Exception( "Child Plug for x point position has been removed." ); + } + return p; +} + +template +const typename RampPlug::XPlugType *RampPlug::pointXPlug( unsigned pointIndex ) const +{ + const XPlugType *p = pointPlug( pointIndex )->template getChild( "x" ); + if( !p ) + { + throw IECore::Exception( "Child Plug for x point position has been removed." ); + } + return p; +} + +template +typename RampPlug::YPlugType *RampPlug::pointYPlug( unsigned pointIndex ) +{ + YPlugType *p = pointPlug( pointIndex )->template getChild( "y" ); + if( !p ) + { + throw IECore::Exception( "Child Plug for y point position has been removed." ); + } + return p; +} + +template +const typename RampPlug::YPlugType *RampPlug::pointYPlug( unsigned pointIndex ) const +{ + const YPlugType *p = pointPlug( pointIndex )->template getChild( "y" ); + if( !p ) + { + throw IECore::Exception( "Child Plug for y point position has been removed." ); + } + return p; +} + + +namespace Gaffer +{ + +// RunTimeTyped specialisation +GAFFER_PLUG_DEFINE_TEMPLATE_TYPE( Gaffer::RampffPlug, RampffPlugTypeId ) +GAFFER_PLUG_DEFINE_TEMPLATE_TYPE( Gaffer::RampfColor3fPlug, RampfColor3fPlugTypeId ) +GAFFER_PLUG_DEFINE_TEMPLATE_TYPE( Gaffer::RampfColor4fPlug, RampfColor4fPlugTypeId ) + +// explicit instantiation +template class RampPlug< IECore::Rampff >; +template class RampPlug< IECore::RampfColor3f >; +template class RampPlug< IECore::RampfColor4f >; + +} diff --git a/src/Gaffer/Reference.cpp b/src/Gaffer/Reference.cpp index 2c5a98234a..0cc3e391ff 100644 --- a/src/Gaffer/Reference.cpp +++ b/src/Gaffer/Reference.cpp @@ -41,7 +41,7 @@ #include "Gaffer/PlugAlgo.h" #include "Gaffer/ScriptNode.h" #include "Gaffer/StandardSet.h" -#include "Gaffer/SplinePlug.h" +#include "Gaffer/RampPlug.h" #include "Gaffer/Spreadsheet.h" #include "Gaffer/StringPlug.h" @@ -81,7 +81,7 @@ bool descendantHasInput( const Plug *plug ) return false; } -bool conformSplinePlugs( const Gaffer::Plug *srcPlug, Gaffer::Plug *dstPlug, bool ignoreDefaultValues ) +bool conformRampPlugs( const Gaffer::Plug *srcPlug, Gaffer::Plug *dstPlug, bool ignoreDefaultValues ) { auto conform = [=] ( auto typedSrc, Gaffer::Plug *dst ) { @@ -110,12 +110,12 @@ bool conformSplinePlugs( const Gaffer::Plug *srcPlug, Gaffer::Plug *dstPlug, boo switch( (Gaffer::TypeId)srcPlug->typeId() ) { - case SplineffPlugTypeId : - return conform( static_cast( srcPlug ), dstPlug ); - case SplinefColor3fPlugTypeId : - return conform( static_cast( srcPlug ), dstPlug ); - case SplinefColor4fPlugTypeId : - return conform( static_cast( srcPlug ), dstPlug ); + case RampffPlugTypeId : + return conform( static_cast( srcPlug ), dstPlug ); + case RampfColor3fPlugTypeId : + return conform( static_cast( srcPlug ), dstPlug ); + case RampfColor4fPlugTypeId : + return conform( static_cast( srcPlug ), dstPlug ); default : return false; } @@ -125,13 +125,13 @@ bool conformSplinePlugs( const Gaffer::Plug *srcPlug, Gaffer::Plug *dstPlug, boo void copyInputsAndValues( Gaffer::Plug *srcPlug, Gaffer::Plug *dstPlug, bool ignoreDefaultValues ) { - // From a user's perspective, we consider SplinePlugs to have a single + // From a user's perspective, we consider RampPlugs to have a single // atomic value. So _any_ edit to _any_ child plug should cause the entire // value to be matched. To do that, we first need to conform the destination // so that it has the same number of points as the source, and then we need // to set values for all plugs. - if( conformSplinePlugs( srcPlug, dstPlug, ignoreDefaultValues ) ) + if( conformRampPlugs( srcPlug, dstPlug, ignoreDefaultValues ) ) { ignoreDefaultValues = false; } @@ -643,14 +643,14 @@ void Reference::loadInternal( const std::filesystem::path &fileName ) plug->setFlags( Plug::Dynamic, false ); if( - runTimeCast( plug ) || - runTimeCast( plug ) || - runTimeCast( plug ) + runTimeCast( plug ) || + runTimeCast( plug ) || + runTimeCast( plug ) ) { // Avoid recursion as it makes it impossible to serialise - // the `x/y` children of spline points. See SplinePlugSerialiser - // for further details of spline serialisation. + // the `x/y` children of ramp points. See RampPlugSerialiser + // for further details of ramp serialisation. continue; } diff --git a/src/Gaffer/SplinePlug.cpp b/src/Gaffer/SplinePlug.cpp deleted file mode 100644 index 880658d40b..0000000000 --- a/src/Gaffer/SplinePlug.cpp +++ /dev/null @@ -1,596 +0,0 @@ -////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) 2011-2012, John Haddon. All rights reserved. -// Copyright (c) 2013, Image Engine Design Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above -// copyright notice, this list of conditions and the following -// disclaimer. -// -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided with -// the distribution. -// -// * Neither the name of John Haddon nor the names of -// any other contributors to this software may be used to endorse or -// promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -////////////////////////////////////////////////////////////////////////// - -#include "Gaffer/SplinePlug.h" - -#include "Gaffer/Action.h" -#include "Gaffer/PlugAlgo.h" - -using namespace Gaffer; - -namespace { - -template -inline Y monotoneSlopeCompute( const Y& deltaY1, const Y& deltaY2, const X& deltaX1, const X& deltaX2 ) -{ - // Using this weighted harmonic mean to compute slopes ensures a monotone curve. - // This is apparently a result by Fritsch and Carlson, from here: - // - // F. N. Fritsch and R. E. Carlson - // SIAM Journal on Numerical Analysis - // Vol. 17, No. 2 (Apr., 1980), pp. 238-246 - // - // Haven't actually gotten ahold of this paper, but stackexchange says that it says this, - // and it seems to work quite well. - if( deltaY1 * deltaY2 > 0.0f ) - { - return 3.0f * ( deltaX1 + deltaX2 ) / ( - ( 2.0f * deltaX2 + deltaX1 ) / deltaY1 + - ( deltaX2 + 2.0f * deltaX1 ) / deltaY2 ); - } - else - { - return 0; - } -} - -template<> -inline Imath::Color3f monotoneSlopeCompute<>( - const Imath::Color3f& deltaY1, const Imath::Color3f& deltaY2, - const float& deltaX1, const float& deltaX2 ) -{ - return Imath::Color3f( - monotoneSlopeCompute( deltaY1[0], deltaY2[0], deltaX1, deltaX2 ), - monotoneSlopeCompute( deltaY1[1], deltaY2[1], deltaX1, deltaX2 ), - monotoneSlopeCompute( deltaY1[2], deltaY2[2], deltaX1, deltaX2 ) - ); -} - -template<> -inline Imath::Color4f monotoneSlopeCompute<>( - const Imath::Color4f& deltaY1, const Imath::Color4f& deltaY2, - const float& deltaX1, const float& deltaX2 ) -{ - return Imath::Color4f( - monotoneSlopeCompute( deltaY1[0], deltaY2[0], deltaX1, deltaX2 ), - monotoneSlopeCompute( deltaY1[1], deltaY2[1], deltaX1, deltaX2 ), - monotoneSlopeCompute( deltaY1[2], deltaY2[2], deltaX1, deltaX2 ), - monotoneSlopeCompute( deltaY1[3], deltaY2[3], deltaX1, deltaX2 ) - ); -} - -// This function translates a set of control points for a MonotoneCubic curve into a set of -// bezier control points. The X values are set up to make each segment linear in X, which -// makes the control point behaviour a bit more predictable when used as a color ramp. -// The Y tangents are adjusted to compensate for the discontinuity in the slope of the -// parameterization across control points, which mean that the X/Y tangent is continuous across -// control points. This curve type seems to work quite well in practice for color ramps. -// -// Note that the way we are evaluating this type of curve by using a spline solver on the X -// axis is ridiculously inefficient - the bezier control points are arranged so it's actually -// always linear, and could be quickly solved analyticly. But because we need to store these -// curves in IECore::Spline, we don't have any way to specify different interpolations for -// X and Y. So we just use bezier curve with appropriately set handles to store our linear X -// curve. -template -void monotoneCubicCVsToBezierCurve( const typename T::PointContainer &cvs, typename T::PointContainer &result ) -{ - // NOTE : It would seem more reasonable to use the slope of the first and last segment for the - // endpoints, instead of clamping to 0. The current argument for clamping to zero is consistency - // with the Htoa ramp - typename T::YType prevSlope = typename T::YType(0); - - typename T::PointContainer::const_iterator i = cvs.begin(); - const typename T::Point *p1 = &*i; - i++; - const typename T::Point *p2 = &*i; - i++; - - for(;;) - { - typename T::YType nextSlope; - - - const typename T::Point *pNext = nullptr; - if( i == cvs.end() ) - { - nextSlope = typename T::YType( 0 ); - } - else - { - pNext = &*i; - - typename T::XType xDelta1 = p2->first - p1->first; - typename T::XType xDelta2 = pNext->first - p2->first; - typename T::YType yDelta1 = p2->second - p1->second; - typename T::YType yDelta2 = pNext->second - p2->second; - - nextSlope = monotoneSlopeCompute( yDelta1 / xDelta1, yDelta2 / xDelta2, xDelta1, xDelta2); - - // NOTE : If we copied everything else about this function, but instead just used: - // 0.5 * ( yDelta1 / xDelta1 + yDelta2 / xDelta2 ) - // for the slope here, this would produce a CatmullRom sort of spline, but with the simpler linear - // behaviour of the knot values. This is what Htoa uses for a CatmullRom ramp, and might be a pretty - // useful curve type ( quite possibly more useful than our current CatmullRom, though it would no - // longer correspond to a CatmullRom basis in OSL ). - } - - typename T::XType xDelta = p2->first - p1->first; - - result.insert( *p1 ); - result.insert( typename T::Point( - p1->first + ( 1.0f/3.0f ) * xDelta, - p1->second + (1.0f/3.0f) * prevSlope * xDelta ) ); - result.insert( typename T::Point( - p1->first + ( 2.0f/3.0f ) * xDelta, - p2->second - (1.0f/3.0f) * nextSlope * xDelta ) ); - - if( i == cvs.end() ) - { - break; - } - else - { - p1 = p2; - p2 = pNext; - prevSlope = nextSlope; - i++; - } - } - - result.insert( *p2 ); -} - -} - -template -const IECore::RunTimeTyped::TypeDescription > SplinePlug::g_typeDescription; - -template -T SplineDefinition::spline() const -{ - T result; - - result.points = points; - - if( interpolation == SplineDefinitionInterpolationLinear ) - { - result.basis = T::Basis::linear(); - } - else if( interpolation == SplineDefinitionInterpolationCatmullRom ) - { - result.basis = T::Basis::catmullRom(); - } - else if( interpolation == SplineDefinitionInterpolationBSpline ) - { - result.basis = T::Basis::bSpline(); - } - else if( interpolation == SplineDefinitionInterpolationMonotoneCubic ) - { - result.basis = T::Basis::bezier(); - if( points.size() > 1 ) - { - result.points.clear(); - monotoneCubicCVsToBezierCurve( points, result.points ); - } - } - else if( interpolation == SplineDefinitionInterpolationConstant ) - { - result.basis = T::Basis::constant(); - } - - int multiplicity = endPointMultiplicity(); - - if( multiplicity && result.points.size() ) - { - for( int i = 0; i < multiplicity - 1; ++i ) - { - result.points.insert( *result.points.begin() ); - result.points.insert( *result.points.rbegin() ); - } - } - - return result; -} - -template -bool SplineDefinition::trimEndPoints() -{ - if( points.empty() ) - { - return true; - } - - // Count how many initial points have an X value matching the first point - typename PointContainer::const_iterator startDuplicates = ++points.begin(); - while( startDuplicates != points.end() && startDuplicates->first == points.begin()->first ) - { - startDuplicates++; - } - // We need to keep one of these points, the rest are duplicates and should be removed - startDuplicates--; - - points.erase( points.begin(), startDuplicates ); - - // Count how many points have an X value matching the last point - typename PointContainer::const_reverse_iterator endDuplicates = ++points.rbegin(); - while( endDuplicates != points.rend() && endDuplicates->first == points.rbegin()->first ) - { - endDuplicates++; - } - - // We need to keep one of these points, the rest are duplicates and should be removed - endDuplicates--; - - points.erase( endDuplicates.base(), points.rbegin().base() ); - - // This originally indicated whether the end point duplication matched the expected multiplicity - // for a certain interpolation. We no longer make assumptions about how the input data handles end - // point multiplicity, and instead just remove any duplicates, so we no longer consider any inputs - // to be invalid. - return true; -} - -template -int SplineDefinition::endPointMultiplicity() const -{ - int multiplicity = 1; - if( interpolation == SplineDefinitionInterpolationCatmullRom ) - { - multiplicity = 2; - } - else if( interpolation == SplineDefinitionInterpolationBSpline ) - { - multiplicity = 3; - } - return multiplicity; -} - - -template -SplinePlug::SplinePlug( const std::string &name, Direction direction, const ValueType &defaultValue, unsigned flags ) - : ValuePlug( name, direction, flags ), m_defaultValue( defaultValue ) -{ - addChild( new IntPlug( "interpolation", direction, SplineDefinitionInterpolationCatmullRom, - SplineDefinitionInterpolationLinear, SplineDefinitionInterpolationConstant ) ); - - setToDefault(); -} - -template -SplinePlug::~SplinePlug() -{ -} - -template -bool SplinePlug::acceptsChild( const GraphComponent *potentialChild ) const -{ - if( children().size() < 1 ) - { - // to let the interpolation plug through during construction - return true; - } - - const ValuePlug *c = IECore::runTimeCast( potentialChild ); - if( !c ) - { - return false; - } - - if( c->children().size()==0 ) - { - // when we're getting loaded from a serialisation, the point plugs are - // added before the point.x and point.y plugs are added, so we have to - // make this concession. - return true; - } - - if( c->children().size()!=2 ) - { - return false; - } - if( !c->getChild( "x" ) ) - { - return false; - } - if( !c->getChild( "y" ) ) - { - return false; - } - return true; -} - -template -PlugPtr SplinePlug::createCounterpart( const std::string &name, Direction direction ) const -{ - Ptr result = new SplinePlug( name, direction, m_defaultValue, getFlags() ); - result->clearPoints(); - for( unsigned i = 0; i < numPoints(); ++i ) - { - const ValuePlug *p = pointPlug( i ); - result->addChild( p->createCounterpart( p->getName(), direction ) ); - } - return result; -} - -template -const T &SplinePlug::defaultValue() const -{ - return m_defaultValue; -} - -template -void SplinePlug::setToDefault() -{ - setValue( m_defaultValue ); - for( const auto &p : ValuePlug::Range( *this ) ) - { - p->resetDefault(); - } -} - -template -void SplinePlug::resetDefault() -{ - ValuePlug::resetDefault(); - - const T newDefault = getValue(); - const T oldDefault = m_defaultValue; - Action::enact( - this, - [this, newDefault] () { - this->m_defaultValue = newDefault; - }, - [this, oldDefault] () { - this->m_defaultValue = oldDefault; - } - ); -} - -template -bool SplinePlug::isSetToDefault() const -{ - for( const auto &p : ValuePlug::RecursiveRange( *this ) ) - { - if( p->children().empty() && PlugAlgo::dependsOnCompute( p.get() ) ) - { - // Value can vary by context, so there is no single "current value", - // and therefore no true concept of whether or not it's at the default. - return false; - } - } - return getValue() == m_defaultValue; -} - -template -IECore::MurmurHash SplinePlug::defaultHash() const -{ - IECore::MurmurHash result; - result.append( typeId() ); - result.append( m_defaultValue.interpolation ); - for( auto &p : m_defaultValue.points ) - { - result.append( p.first ); - result.append( p.second ); - } - return result; -} - -template -void SplinePlug::setValue( const T &value ) -{ - interpolationPlug()->setValue( value.interpolation ); - - typename T::PointContainer::const_iterator it = value.points.begin(); - typename T::PointContainer::const_iterator eIt = value.points.end(); - - unsigned existingPoints = numPoints(); - unsigned i = 0; - for( ; it!=eIt; ++it ) - { - if( i >= existingPoints ) - { - addPoint(); - } - pointXPlug( i )->setValue( it->first ); - pointYPlug( i )->setValue( it->second ); - i++; - } - - // remove unneeded preexisting points - while( numPoints() > i ) - { - removeChild( pointPlug( i ) ); - } -} - -template -T SplinePlug::getValue() const -{ - T result; - result.interpolation = (SplineDefinitionInterpolation)interpolationPlug()->getValue(); - - unsigned n = numPoints(); - for( unsigned i=0; igetValue(), pointYPlug( i )->getValue() ) ); - } - - return result; -} - - -template -IntPlug *SplinePlug::interpolationPlug() -{ - return getChild( "interpolation" ); -} - -template -const IntPlug *SplinePlug::interpolationPlug() const -{ - return getChild( "interpolation" ); -} - -template -unsigned SplinePlug::numPoints() const -{ - return children().size() - 1; -} - -template -unsigned SplinePlug::addPoint() -{ - const unsigned n = numPoints(); - ValuePlugPtr p = new ValuePlug( "p0", direction() ); - p->setFlags( Plug::Dynamic, true ); - - typename XPlugType::Ptr x = new XPlugType( "x", direction(), typename T::XType( 0 ) ); - x->setFlags( Plug::Dynamic, true ); - p->addChild( x ); - - typename YPlugType::Ptr y = new YPlugType( "y", direction(), typename T::YType( 0 ) ); - y->setFlags( Plug::Dynamic, true ); - p->addChild( y ); - - addChild( p ); - - return n; -} - -template -void SplinePlug::removePoint( unsigned pointIndex ) -{ - removeChild( pointPlug( pointIndex ) ); -} - -template -void SplinePlug::clearPoints() -{ - unsigned i = numPoints(); - if( !i ) - { - return; - } - - do { - removePoint( --i ); - } while( i!=0 ); -} - -template -ValuePlug *SplinePlug::pointPlug( unsigned pointIndex ) -{ - if( pointIndex >= numPoints() ) - { - throw IECore::Exception( "Point index out of range." ); - } - return getChild( pointIndex + 1 ); // plus one is to skip interpolation plug -} - -template -const ValuePlug *SplinePlug::pointPlug( unsigned pointIndex ) const -{ - if( pointIndex >= numPoints() ) - { - throw IECore::Exception( "Point index out of range." ); - } - return getChild( pointIndex + 1 ); // plus one is to skip interpolation plug -} - -template -typename SplinePlug::XPlugType *SplinePlug::pointXPlug( unsigned pointIndex ) -{ - XPlugType *p = pointPlug( pointIndex )->template getChild( "x" ); - if( !p ) - { - throw IECore::Exception( "Child Plug for x point position has been removed." ); - } - return p; -} - -template -const typename SplinePlug::XPlugType *SplinePlug::pointXPlug( unsigned pointIndex ) const -{ - const XPlugType *p = pointPlug( pointIndex )->template getChild( "x" ); - if( !p ) - { - throw IECore::Exception( "Child Plug for x point position has been removed." ); - } - return p; -} - -template -typename SplinePlug::YPlugType *SplinePlug::pointYPlug( unsigned pointIndex ) -{ - YPlugType *p = pointPlug( pointIndex )->template getChild( "y" ); - if( !p ) - { - throw IECore::Exception( "Child Plug for y point position has been removed." ); - } - return p; -} - -template -const typename SplinePlug::YPlugType *SplinePlug::pointYPlug( unsigned pointIndex ) const -{ - const YPlugType *p = pointPlug( pointIndex )->template getChild( "y" ); - if( !p ) - { - throw IECore::Exception( "Child Plug for y point position has been removed." ); - } - return p; -} - - -namespace Gaffer -{ - -// RunTimeTyped specialisation -GAFFER_PLUG_DEFINE_TEMPLATE_TYPE( Gaffer::SplineffPlug, SplineffPlugTypeId ) -GAFFER_PLUG_DEFINE_TEMPLATE_TYPE( Gaffer::SplinefColor3fPlug, SplinefColor3fPlugTypeId ) -GAFFER_PLUG_DEFINE_TEMPLATE_TYPE( Gaffer::SplinefColor4fPlug, SplinefColor4fPlugTypeId ) - -// explicit instantiation -template struct SplineDefinition< IECore::Splineff >; -template struct SplineDefinition< IECore::SplinefColor3f >; -template struct SplineDefinition< IECore::SplinefColor4f >; -template class SplinePlug< SplineDefinitionff >; -template class SplinePlug< SplineDefinitionfColor3f >; -template class SplinePlug< SplineDefinitionfColor4f >; - -} diff --git a/src/Gaffer/ValuePlug.cpp b/src/Gaffer/ValuePlug.cpp index 3de176e7bc..988806ffcd 100644 --- a/src/Gaffer/ValuePlug.cpp +++ b/src/Gaffer/ValuePlug.cpp @@ -1095,7 +1095,7 @@ void ValuePlug::parentChanged( Gaffer::GraphComponent *oldParent ) // Addition or removal of a child is considered to change a plug's value, // so we emit the appropriate signal. This is mostly of use for the - // SplinePlug and CompoundDataPlug, where points and data members + // RampPlug and CompoundDataPlug, where points and data members // are added and removed by adding and removing plugs. if( auto p = IECore::runTimeCast( oldParent ) ) { diff --git a/src/GafferBindings/ValuePlugBinding.cpp b/src/GafferBindings/ValuePlugBinding.cpp index 26bdc9ae6d..cafe28e9c2 100644 --- a/src/GafferBindings/ValuePlugBinding.cpp +++ b/src/GafferBindings/ValuePlugBinding.cpp @@ -102,7 +102,7 @@ std::string valueSerialisationWalk( const Gaffer::ValuePlug *plug, const std::st // Can't condense, because can't get value at this level. // We also disable condensing at outer levels in this case, // because otherwise we hit problems trying to serialise - // SplinePlugs. + // RampPlugs. canCondense = false; return childSerialisations; } diff --git a/src/GafferCycles/IECoreCyclesPreview/ShaderNetworkAlgo.cpp b/src/GafferCycles/IECoreCyclesPreview/ShaderNetworkAlgo.cpp index 407b521041..1b6a9a8b60 100644 --- a/src/GafferCycles/IECoreCyclesPreview/ShaderNetworkAlgo.cpp +++ b/src/GafferCycles/IECoreCyclesPreview/ShaderNetworkAlgo.cpp @@ -47,7 +47,7 @@ #include "IECore/MessageHandler.h" #include "IECore/SearchPath.h" #include "IECore/SimpleTypedData.h" -#include "IECore/SplineData.h" +#include "IECore/RampData.h" #include "IECore/VectorTypedData.h" #include "boost/algorithm/string.hpp" @@ -189,24 +189,24 @@ ccl::ShaderNode *convertWalk( const ShaderNetwork::Parameter &outputParameter, c // "__", revert that change here. string parameterName = boost::replace_first_copy( namedParameter.first.string(), "__", "." ); - if( const SplineffData *splineData = runTimeCast( namedParameter.second.get() ) ) + if( const RampffData *rampData = runTimeCast( namedParameter.second.get() ) ) { - // For OSL, splines are handled by convertToOSLConventions + // For OSL, ramps are handled by convertToOSLConventions assert( !isOSLShader ); if( const ccl::SocketType *socket = node->type->find_input( ccl::ustring( parameterName.c_str() ) ) ) { - SocketAlgo::setRampSocket( node, socket, splineData->readable() ); + SocketAlgo::setRampSocket( node, socket, rampData->readable() ); } } - else if( const SplinefColor3fData *splineData = runTimeCast( namedParameter.second.get() ) ) + else if( const RampfColor3fData *rampData = runTimeCast( namedParameter.second.get() ) ) { - // For OSL, splines are handled by convertToOSLConventions + // For OSL, ramps are handled by convertToOSLConventions assert( !isOSLShader ); if( const ccl::SocketType *socket = node->type->find_input( ccl::ustring( parameterName.c_str() ) ) ) { - SocketAlgo::setRampSocket( node, socket, splineData->readable() ); + SocketAlgo::setRampSocket( node, socket, rampData->readable() ); } } else if( isImageTexture && parameterName == "filename" ) diff --git a/src/GafferCycles/IECoreCyclesPreview/SocketAlgo.cpp b/src/GafferCycles/IECoreCyclesPreview/SocketAlgo.cpp index c725002b63..351edea5a3 100644 --- a/src/GafferCycles/IECoreCyclesPreview/SocketAlgo.cpp +++ b/src/GafferCycles/IECoreCyclesPreview/SocketAlgo.cpp @@ -521,25 +521,29 @@ void setSocket( ccl::Node *node, const std::string &name, const IECore::Data *va } } -void setRampSocket( ccl::Node *node, const ccl::SocketType *socket, const IECore::Splineff &spline ) +void setRampSocket( ccl::Node *node, const ccl::SocketType *socket, const IECore::Rampff &ramp ) { - ccl::array ramp( RAMP_TABLE_SIZE ); + IECore::Splineff evaluator = ramp.evaluator(); + + ccl::array rampTable( RAMP_TABLE_SIZE ); for (int i = 0; i < RAMP_TABLE_SIZE; i++) { - ramp[i] = spline( (float)i / (float)(RAMP_TABLE_SIZE - 1) ); + rampTable[i] = evaluator( (float)i / (float)(RAMP_TABLE_SIZE - 1) ); } - node->set( *socket, ramp ); + node->set( *socket, rampTable ); } -void setRampSocket( ccl::Node *node, const ccl::SocketType *socket, const IECore::SplinefColor3f &spline ) +void setRampSocket( ccl::Node *node, const ccl::SocketType *socket, const IECore::RampfColor3f &ramp ) { - ccl::array ramp( RAMP_TABLE_SIZE ); + IECore::SplinefColor3f evaluator = ramp.evaluator(); + + ccl::array rampTable( RAMP_TABLE_SIZE ); for (int i = 0; i < RAMP_TABLE_SIZE; i++) { - Color3f solve = spline( (float)i / (float)(RAMP_TABLE_SIZE - 1) ); - ramp[i] = ccl::make_float3( solve.x, solve.y, solve.z ); + Color3f solve = evaluator( (float)i / (float)(RAMP_TABLE_SIZE - 1) ); + rampTable[i] = ccl::make_float3( solve.x, solve.y, solve.z ); } - node->set( *socket, ramp ); + node->set( *socket, rampTable ); } ccl::ParamValue setParamValue( const IECore::InternedString &name, const IECore::Data *value ) diff --git a/src/GafferCycles/SocketHandler.cpp b/src/GafferCycles/SocketHandler.cpp index afafcf3630..d569f0fecc 100644 --- a/src/GafferCycles/SocketHandler.cpp +++ b/src/GafferCycles/SocketHandler.cpp @@ -45,7 +45,7 @@ #include "Gaffer/Node.h" #include "Gaffer/PlugAlgo.h" #include "Gaffer/ScriptNode.h" -#include "Gaffer/SplinePlug.h" +#include "Gaffer/RampPlug.h" #include "Gaffer/StringPlug.h" #include "Gaffer/TypedPlug.h" @@ -265,11 +265,11 @@ Gaffer::Plug *setupPlug( const IECore::InternedString &socketName, int socketTyp case ccl::SocketType::FLOAT_ARRAY : { - IECore::Splineff::PointContainer points; + IECore::Rampff::PointContainer points; points.insert( std::pair( 0.0f, 0.0f ) ); points.insert( std::pair( 1.0f, 1.0f ) ); - return setupTypedPlug( socketName, plugParent, direction, SplineDefinitionff( points, SplineDefinitionInterpolationCatmullRom ) ); + return setupTypedPlug( socketName, plugParent, direction, Rampff( points, RampInterpolation::CatmullRom ) ); } case ccl::SocketType::COLOR_ARRAY : @@ -277,11 +277,11 @@ Gaffer::Plug *setupPlug( const IECore::InternedString &socketName, int socketTyp { - IECore::SplinefColor3f::PointContainer points; + IECore::RampfColor3f::PointContainer points; points.insert( std::pair( 0.0f, Color3f( 0.0f ) ) ); points.insert( std::pair( 1.0f, Color3f( 1.0f ) ) ); - return setupTypedPlug( socketName, plugParent, direction, SplineDefinitionfColor3f( points, SplineDefinitionInterpolationCatmullRom ) ); + return setupTypedPlug( socketName, plugParent, direction, RampfColor3f( points, RampInterpolation::CatmullRom ) ); } @@ -430,15 +430,15 @@ Gaffer::Plug *setupPlug( const ccl::NodeType *nodeType, const ccl::SocketType so case ccl::SocketType::FLOAT_ARRAY : { - IECore::Splineff::PointContainer points; + IECore::Rampff::PointContainer points; points.insert( std::pair( 0.0f, 0.0f ) ); points.insert( std::pair( 1.0f, 1.0f ) ); - plug = setupTypedPlug( + plug = setupTypedPlug( nodeType, socketType, plugParent, direction, - SplineDefinitionff( points, SplineDefinitionInterpolationCatmullRom ) + Rampff( points, RampInterpolation::CatmullRom ) ); } break; @@ -447,15 +447,15 @@ Gaffer::Plug *setupPlug( const ccl::NodeType *nodeType, const ccl::SocketType so case ccl::SocketType::VECTOR_ARRAY : { - IECore::SplinefColor3f::PointContainer points; + IECore::RampfColor3f::PointContainer points; points.insert( std::pair( 0.0f, Color3f( 0.0f ) ) ); points.insert( std::pair( 1.0f, Color3f( 1.0f ) ) ); - plug = setupTypedPlug( + plug = setupTypedPlug( nodeType, socketType, plugParent, direction, - SplineDefinitionfColor3f( points, SplineDefinitionInterpolationCatmullRom ) + RampfColor3f( points, RampInterpolation::CatmullRom ) ); } break; diff --git a/src/GafferImage/Ramp.cpp b/src/GafferImage/Ramp.cpp index dd601b6d78..beeac7eeab 100644 --- a/src/GafferImage/Ramp.cpp +++ b/src/GafferImage/Ramp.cpp @@ -60,10 +60,10 @@ Ramp::Ramp( const std::string &name ) addChild( new FormatPlug( "format" ) ); addChild( new V2fPlug( "startPosition", Plug::In ) ); addChild( new V2fPlug( "endPosition", Plug::In ) ); - SplinefColor4fPlug::ValueType rampDefault; - rampDefault.points.insert( SplinefColor4fPlug::ValueType::Point( 0.0f, Color4f( 0.0f, 0.0f, 0.0f, 0.0f ) ) ); - rampDefault.points.insert( SplinefColor4fPlug::ValueType::Point( 1.0f, Color4f( 1.0f, 1.0f, 1.0f, 1.0f ) ) ); - addChild( new SplinefColor4fPlug( "ramp", Plug::In, rampDefault ) ); + RampfColor4fPlug::ValueType rampDefault; + rampDefault.points.insert( RampfColor4fPlug::ValueType::Point( 0.0f, Color4f( 0.0f, 0.0f, 0.0f, 0.0f ) ) ); + rampDefault.points.insert( RampfColor4fPlug::ValueType::Point( 1.0f, Color4f( 1.0f, 1.0f, 1.0f, 1.0f ) ) ); + addChild( new RampfColor4fPlug( "ramp", Plug::In, rampDefault ) ); addChild( new StringPlug( "layer" ) ); addChild( new Transform2DPlug( "transform" ) ); } @@ -102,14 +102,14 @@ const Gaffer::V2fPlug *Ramp::endPositionPlug() const return getChild( g_firstPlugIndex + 2 ); } -Gaffer::SplinefColor4fPlug *Ramp::rampPlug() +Gaffer::RampfColor4fPlug *Ramp::rampPlug() { - return getChild( g_firstPlugIndex + 3 ); + return getChild( g_firstPlugIndex + 3 ); } -const Gaffer::SplinefColor4fPlug *Ramp::rampPlug() const +const Gaffer::RampfColor4fPlug *Ramp::rampPlug() const { - return getChild( g_firstPlugIndex + 3 ); + return getChild( g_firstPlugIndex + 3 ); } Gaffer::StringPlug *Ramp::layerPlug() @@ -236,7 +236,7 @@ IECore::ConstFloatVectorDataPtr Ramp::computeChannelData( const std::string &cha { const int channelIndex = ImageAlgo::colorIndex( context->get( ImagePlug::channelNameContextName ) ); - const IECore::SplinefColor4f ramp = rampPlug()->getValue().spline(); + const IECore::SplinefColor4f ramp = rampPlug()->getValue().evaluator(); const M33f inverseTransform = transformPlug()->matrix().inverse(); const V2f startPosition = startPositionPlug()->getValue(); diff --git a/src/GafferModule/GafferModule.cpp b/src/GafferModule/GafferModule.cpp index 17f002c855..28cca002dc 100644 --- a/src/GafferModule/GafferModule.cpp +++ b/src/GafferModule/GafferModule.cpp @@ -68,7 +68,7 @@ #include "SerialisationBinding.h" #include "SetBinding.h" #include "SignalsBinding.h" -#include "SplinePlugBinding.h" +#include "RampPlugBinding.h" #include "SpreadsheetBinding.h" #include "StringPlugBinding.h" #include "SubGraphBinding.h" @@ -269,7 +269,7 @@ BOOST_PYTHON_MODULE( _Gaffer ) bindDirtyPropagationScope(); bindUndoScope(); bindCompoundNumericPlug(); - bindSplinePlug(); + bindRampPlug(); bindBoxPlug(); bindExpression(); bindTransformPlug(); diff --git a/src/GafferModule/SplinePlugBinding.cpp b/src/GafferModule/RampPlugBinding.cpp similarity index 62% rename from src/GafferModule/SplinePlugBinding.cpp rename to src/GafferModule/RampPlugBinding.cpp index 1d06ed38ff..8208e3a8d0 100644 --- a/src/GafferModule/SplinePlugBinding.cpp +++ b/src/GafferModule/RampPlugBinding.cpp @@ -37,13 +37,13 @@ #include "boost/python.hpp" -#include "SplinePlugBinding.h" +#include "RampPlugBinding.h" #include "GafferBindings/PlugBinding.h" #include "GafferBindings/ValuePlugBinding.h" #include "Gaffer/Node.h" -#include "Gaffer/SplinePlug.h" +#include "Gaffer/RampPlug.h" #include "Gaffer/TypedPlug.h" #include "IECorePython/IECoreBinding.h" @@ -56,86 +56,10 @@ using namespace Gaffer; namespace { -template -std::string splineDefinitionRepr( object x ) -{ - std::stringstream s; - const std::string name = extract( x.attr( "__class__").attr( "__name__" ) ); - s << "Gaffer." << name << "( "; - const T splineDefinition = extract( x ); - s << "("; - int i = 0; - int l = splineDefinition.points.size(); - typename T::PointContainer::const_iterator it; - for( it=splineDefinition.points.begin(); it!=splineDefinition.points.end(); it++, i++ ) - { - // TODO - without this const_cast I get a link error because the const version of repr - // hasn't been defined - s << " ( " << it->first << ", " << IECorePython::repr( const_cast( it->second ) ) << " )"; - if( i!=l-1 ) - { - s << ","; - } - } - s << "), "; - s << "Gaffer.SplineDefinitionInterpolation( " << splineDefinition.interpolation << " )"; - s << ")"; - return s.str(); -} - -template -T *splineDefinitionConstruct( object o, const SplineDefinitionInterpolation &interpolation ) -{ - typename T::PointContainer points; - int s = extract( o.attr( "__len__" )() ); - for( int i=0; i( e.attr( "__len__" )() ); - if( es!=2 ) - { - throw IECore::Exception( "Each entry in the point sequence must contain two values." ); - } - object xo = e[0]; - object yo = e[1]; - float x = extract( xo ); - typename T::YType y = extract( yo ); - points.insert( typename T::PointContainer::value_type( x, y ) ); - } - return new T( points, interpolation ); -} - -template -boost::python::tuple splineDefinitionPoints( const T &s ) -{ - boost::python::list p; - typename T::PointContainer::const_iterator it; - for( it=s.points.begin(); it!=s.points.end(); it++ ) - { - p.append( make_tuple( it->first, it->second ) ); - } - return boost::python::tuple( p ); -} - -template -void bindSplineDefinition( const char *name) -{ - class_( name ) - .def( "__init__", make_constructor( &splineDefinitionConstruct ) ) - .def( "__repr__", &splineDefinitionRepr ) - .def( "points", &splineDefinitionPoints, "Read only access to the control points as a tuple of tuples of ( x, y ) pairs." ) - .def_readwrite("interpolation", &T::interpolation) - .def( self==self ) - .def( self!=self ) - .def( "spline", &T::spline ) - .def( "trimEndPoints", &T::trimEndPoints ) - ; -} - const IECore::InternedString g_interpolation( "interpolation" ); const IECore::InternedString g_omitParentNodePlugValues( "valuePlugSerialiser:omitParentNodePlugValues" ); -class SplinePlugSerialiser : public ValuePlugSerialiser +class RampPlugSerialiser : public ValuePlugSerialiser { public : @@ -145,7 +69,7 @@ class SplinePlugSerialiser : public ValuePlugSerialiser std::string result = ValuePlugSerialiser::postConstructor( plug, identifier, serialisation ); if( !omitValue( plug, serialisation ) ) { - // This isn't ideal, but the newly constructed spline plug will already have child plugs representing the points for the + // This isn't ideal, but the newly constructed ramp plug will already have child plugs representing the points for the // default value. So we get rid of those so the real value can be loaded appropriately by serialising plug constructors // (see below). result += identifier + ".clearPoints()\n"; @@ -256,26 +180,15 @@ void bind() .def( "pointYPlug", &pointYPlug ) ; - Serialisation::registerSerialiser( T::staticTypeId(), new SplinePlugSerialiser ); + Serialisation::registerSerialiser( T::staticTypeId(), new RampPlugSerialiser ); } } // namespace -void GafferModule::bindSplinePlug() +void GafferModule::bindRampPlug() { - enum_( "SplineDefinitionInterpolation" ) - .value( "Linear", SplineDefinitionInterpolationLinear ) - .value( "CatmullRom", SplineDefinitionInterpolationCatmullRom ) - .value( "BSpline", SplineDefinitionInterpolationBSpline ) - .value( "MonotoneCubic", SplineDefinitionInterpolationMonotoneCubic ) - .value( "Constant", SplineDefinitionInterpolationConstant ) - ; - - bindSplineDefinition( "SplineDefinitionff" ); - bindSplineDefinition( "SplineDefinitionfColor3f" ); - bindSplineDefinition( "SplineDefinitionfColor4f" ); - bind(); - bind(); - bind(); + bind(); + bind(); + bind(); } diff --git a/src/GafferModule/SplinePlugBinding.h b/src/GafferModule/RampPlugBinding.h similarity index 98% rename from src/GafferModule/SplinePlugBinding.h rename to src/GafferModule/RampPlugBinding.h index 78f7239189..adafad34c9 100644 --- a/src/GafferModule/SplinePlugBinding.h +++ b/src/GafferModule/RampPlugBinding.h @@ -39,6 +39,6 @@ namespace GafferModule { -void bindSplinePlug(); +void bindRampPlug(); } // namespace GafferModule diff --git a/src/GafferOSL/OSLCode.cpp b/src/GafferOSL/OSLCode.cpp index fd98307e88..719841f746 100644 --- a/src/GafferOSL/OSLCode.cpp +++ b/src/GafferOSL/OSLCode.cpp @@ -40,7 +40,7 @@ #include "Gaffer/Metadata.h" #include "Gaffer/Process.h" -#include "Gaffer/SplinePlug.h" +#include "Gaffer/RampPlug.h" #include "Gaffer/StringPlug.h" #include "IECore/Exception.h" @@ -69,7 +69,7 @@ using namespace GafferOSL; namespace { -string colorSplineParameter( const SplinefColor3fPlug *plug ) +string colorSplineParameter( const RampfColor3fPlug *plug ) { string result; result += "\tfloat " + plug->getName().string() + "Positions[] = { 0, 0, 1, 1 },\n"; @@ -81,9 +81,9 @@ string colorSplineParameter( const SplinefColor3fPlug *plug ) string parameter( const Plug *plug ) { const Gaffer::TypeId plugType = (Gaffer::TypeId)plug->typeId(); - if( plugType == SplinefColor3fPlugTypeId ) + if( plugType == RampfColor3fPlugTypeId ) { - return colorSplineParameter( static_cast( plug ) ); + return colorSplineParameter( static_cast( plug ) ); } string type; diff --git a/src/GafferOSL/OSLShader.cpp b/src/GafferOSL/OSLShader.cpp index 47ab8950ca..32dd4dc5fe 100644 --- a/src/GafferOSL/OSLShader.cpp +++ b/src/GafferOSL/OSLShader.cpp @@ -45,7 +45,7 @@ #include "Gaffer/Metadata.h" #include "Gaffer/NumericPlug.h" #include "Gaffer/PlugAlgo.h" -#include "Gaffer/SplinePlug.h" +#include "Gaffer/RampPlug.h" #include "Gaffer/StringPlug.h" #include "Gaffer/Private/IECorePreview/LRUCache.h" @@ -831,104 +831,77 @@ Plug *loadClosureParameter( const OSLQuery::Parameter *parameter, const Interned return plug.get(); } -void updatePoints( Splineff::PointContainer &points, const OSLQuery::Parameter *positionsParameter, const OSLQuery::Parameter *valuesParameter, size_t maxSize ) -{ - const vector &positions = positionsParameter->fdefault; - const vector &values = valuesParameter->fdefault; - - for( size_t i = 0; ( i < positions.size() ) && ( i < values.size() ) && i < maxSize; ++i ) - { - points.insert( Splineff::Point( positions[i], values[i] ) ); - } -} - -void updatePoints( SplinefColor3f::PointContainer &points, const OSLQuery::Parameter *positionsParameter, const OSLQuery::Parameter *valuesParameter, size_t maxSize ) -{ - const vector &positions = positionsParameter->fdefault; - const vector &values = valuesParameter->fdefault; - - for( size_t i = 0; i < positions.size() && i*3+2 < values.size() && i < maxSize; ++i ) - { - points.insert( - SplinefColor3f::Point( - positions[i], - Color3f( - values[i*3], - values[i*3+1], - values[i*3+2] - ) - ) - ); - } - - -} - // From https://gitlab.com/3Delight/3delight-for-houdini/-/blob/master/osl_utilities.cpp -SplineDefinitionInterpolation basisFrom3DelightInt( int basis ) +std::string basisStringFrom3DelightInt( int basis ) { switch( basis ) { - case 0 : return SplineDefinitionInterpolationConstant; - case 1 : return SplineDefinitionInterpolationLinear; - case 2 : return SplineDefinitionInterpolationMonotoneCubic; - default : return SplineDefinitionInterpolationCatmullRom; - } -} - -SplineDefinitionInterpolation basisFromString( const std::string &basis ) -{ - if( basis == "bspline" ) - { - return SplineDefinitionInterpolationBSpline; - } - else if( basis == "linear" ) - { - return SplineDefinitionInterpolationLinear; - } - else if( basis == "constant" ) - { - return SplineDefinitionInterpolationConstant; + case 0 : return "constant"; + case 1 : return "linear"; + case 2 : return "monotonecubic"; + default : return "catmullrom"; } - else if( basis == "monotonecubic" ) - { - return SplineDefinitionInterpolationMonotoneCubic; - } - - return SplineDefinitionInterpolationCatmullRom; } -struct SplinePlugArguments +struct RampPlugArguments { std::string name; - std::variant< SplineDefinitionff, SplineDefinitionfColor3f > defaultValue; + std::variant< Rampff, RampfColor3f > defaultValue; }; -template -SplineDefinitionType loadSplineDefault( const OSLQuery::Parameter *positionsParameter, const OSLQuery::Parameter *valuesParameter, const OSLQuery::Parameter *basisParameter, const OSLQuery::Parameter *countParameter, const std::string &name ) +template +RampType loadRampDefault( const OSLQuery::Parameter *positionsParameter, const OSLQuery::Parameter *valuesParameter, const OSLQuery::Parameter *basisParameter, const OSLQuery::Parameter *countParameter, const std::string &name ) { - SplineDefinitionType defaultValue; + RampType defaultValue; + + std::string basisString; if( basisParameter->type.basetype == TypeDesc::INT ) { - defaultValue.interpolation = basisFrom3DelightInt( basisParameter->idefault.front() ); + basisString = basisStringFrom3DelightInt( basisParameter->idefault.front() ); } else { - defaultValue.interpolation = basisFromString( basisParameter->sdefault.front().string() ); + basisString = basisParameter->sdefault.front().string(); } + std::vector positions; + std::vector values; + const vector &rawPositions = positionsParameter->fdefault; + const vector &rawValues = valuesParameter->fdefault; + size_t maxSize = std::numeric_limits::max(); if( countParameter ) { maxSize = countParameter->idefault.front(); } - updatePoints( defaultValue.points, positionsParameter, valuesParameter, maxSize ); + if constexpr( std::is_same_v< typename RampType::YType, Color3f > ) + { + for( size_t i = 0; i < rawPositions.size() && i*3+2 < rawValues.size() && i < maxSize; ++i ) + { + values.push_back( + Color3f( + rawValues[i*3], + rawValues[i*3+1], + rawValues[i*3+2] + ) + ); + } + } + else + { + for( size_t i = 0; i < rawPositions.size() && i < rawValues.size() && i < maxSize; ++i ) + { + values.push_back( rawValues[i] ); + } + } + + for( size_t i = 0; i < rawPositions.size() && i < values.size() && i < maxSize; ++i ) + { + positions.push_back( rawPositions[i] ); + } - // The OSL spline representation includes the need for duplicated end points in order to hit the end. - // We need to remove these. We ignore the success or failure of trimming because some renderers have - // default values that are already trimmed. - defaultValue.trimEndPoints(); + defaultValue.fromOSL( basisString, positions, values, name ); return defaultValue; } @@ -1066,7 +1039,7 @@ bool findSplineParametersFromPositions( const std::string &shaderName, const OSL return success; } -std::optional splinePlugArgumentsFromPositions( const std::string &shaderName, const OSLQuery &query, const OSLQuery::Parameter *positionsParameter, const std::string &prefix, std::unordered_set ¶metersAlreadyProcessed ) +std::optional rampPlugArgumentsFromPositions( const std::string &shaderName, const OSLQuery &query, const OSLQuery::Parameter *positionsParameter, const std::string &prefix, std::unordered_set ¶metersAlreadyProcessed ) { string nameWithoutSuffix; @@ -1074,24 +1047,24 @@ std::optional splinePlugArgumentsFromPositions( const std:: const OSLQuery::Parameter *basisParameter; const OSLQuery::Parameter *countParameter; - SplinePlugArguments result; + RampPlugArguments result; if( !findSplineParametersFromPositions( shaderName, query, positionsParameter, nameWithoutSuffix, valuesParameter, basisParameter, countParameter, parametersAlreadyProcessed ) ) { - return std::optional(); + return std::optional(); } result.name = nameWithoutSuffix.substr( prefix.size() ); if( valuesParameter->type.vecsemantics == TypeDesc::COLOR ) { - result.defaultValue = loadSplineDefault( positionsParameter, valuesParameter, basisParameter, countParameter, result.name ); + result.defaultValue = loadRampDefault( positionsParameter, valuesParameter, basisParameter, countParameter, result.name ); } else { - result.defaultValue = loadSplineDefault( positionsParameter, valuesParameter, basisParameter, countParameter, result.name ); + result.defaultValue = loadRampDefault( positionsParameter, valuesParameter, basisParameter, countParameter, result.name ); } - return std::make_optional( result ); + return std::make_optional( result ); } // Forward declaration so loadStructParameter() can call it. @@ -1248,7 +1221,7 @@ Plug *loadShaderParameter( const std::string shaderName, const OSLQuery &query, } template -Gaffer::Plug *loadSplineParameterFromDefault( const InternedString &name, const typename PlugType::ValueType &defaultValue, Gaffer::Plug *parent ) +Gaffer::Plug *loadRampParameterFromDefault( const InternedString &name, const typename PlugType::ValueType &defaultValue, Gaffer::Plug *parent ) { PlugType *existingPlug = parent->getChild( name ); if( existingPlug && existingPlug->defaultValue() == defaultValue ) @@ -1261,7 +1234,7 @@ Gaffer::Plug *loadSplineParameterFromDefault( const InternedString &name, const // Other parameters are loaded using replacePlug if existingPlug is non-null, so existing connections // and values are preserved. It might make sense to do that here as well, but there could be // inconsistencies if the length of the default value has changed, and the user has only overridden - // a few control points ... we haven't tested how well replacePlug works on splines, so for the moment + // a few control points ... we haven't tested how well replacePlug works on ramps, so for the moment // we'll just throw away previous values here ( this currently isn't causing any problems, so we won't // change it ). @@ -1277,16 +1250,16 @@ void loadShaderParameters( const std::string &shaderName, const OSLQuery &query, set validPlugs; // Spline parameters are a nasty special case because multiple shader - // parameters become a single plug on the node, so we deal with them + // parameters become a single ramp plug on the node, so we deal with them // first, and use this set to record parameters that have already been - // processed as part of a spline. + // processed as part of a ramp. std::unordered_set parametersAlreadyProcessed; - std::unordered_map splinePlugArguments; + std::unordered_map rampPlugArguments; for( size_t i = 0; i < query.nparams(); ++i ) { - // We will check whether this parameter fits as the positions parameter of a spline + // We will check whether this parameter fits as the positions parameter of a ramp const OSLQuery::Parameter *positionsParameter = query.getparam( i ); const Plug::Direction direction = positionsParameter->isoutput ? Plug::Out : Plug::In; if( direction != parent->direction() ) @@ -1306,16 +1279,15 @@ void loadShaderParameters( const std::string &shaderName, const OSLQuery &query, continue; } - auto splineP = splinePlugArgumentsFromPositions( shaderName, query, positionsParameter, prefix, parametersAlreadyProcessed ); + auto rampP = rampPlugArgumentsFromPositions( shaderName, query, positionsParameter, prefix, parametersAlreadyProcessed ); - // This is a very weird way of saying "The variant isn't empty", but it seems to be the modern C++ convention ) - if( splineP ) + if( rampP ) { - splinePlugArguments[positionsParameter] = *splineP; + rampPlugArguments[positionsParameter] = *rampP; } } - // Now process all the normal parameters that aren't part of a spline + // Now process all the normal parameters that aren't part of a ramp for( size_t i = 0; i < query.nparams(); ++i ) { const OSLQuery::Parameter *parameter = query.getparam( i ); @@ -1339,25 +1311,25 @@ void loadShaderParameters( const std::string &shaderName, const OSLQuery &query, if( parametersAlreadyProcessed.count( parameter ) ) { - // Already loaded as part of a spline + // Already loaded as part of a ramp continue; } Plug *plug = nullptr; - auto splineIt = splinePlugArguments.find( parameter ); - if( splineIt != splinePlugArguments.end() ) + auto rampIt = rampPlugArguments.find( parameter ); + if( rampIt != rampPlugArguments.end() ) { - // This is the key parameter for the spline, time to output this spline - // ( We need to wait until now to output the spline so it gets interleaved in proper - // order with the non-spline parameters ) - if( std::holds_alternative< SplineDefinitionfColor3f >( splineIt->second.defaultValue ) ) + // This is the key parameter for the ramp, time to output this ramp + // ( We need to wait until now to output the ramp so it gets interleaved in proper + // order with the non-ramp parameters ) + if( std::holds_alternative< RampfColor3f >( rampIt->second.defaultValue ) ) { - plug = loadSplineParameterFromDefault( splineIt->second.name, std::get( splineIt->second.defaultValue ), parent ); + plug = loadRampParameterFromDefault( rampIt->second.name, std::get( rampIt->second.defaultValue ), parent ); } else { - plug = loadSplineParameterFromDefault( splineIt->second.name, std::get( splineIt->second.defaultValue ), parent ); + plug = loadRampParameterFromDefault( rampIt->second.name, std::get( rampIt->second.defaultValue ), parent ); } } else @@ -1588,10 +1560,10 @@ static IECore::ConstCompoundDataPtr metadataGetter( const std::string &shaderNam std::unordered_set parametersAlreadyProcessed; - // First look for splines, where any metadata on component parameters should be registered onto the spline plug + // First look for ramps, where any metadata on component parameters should be registered onto the ramp plug for( size_t i = 0; i < query.nparams(); ++i ) { - // We will check whether this parameter fits as the positions parameter of a spline + // We will check whether this parameter fits as the positions parameter of a ramp const OSLQuery::Parameter *positionsParameter = query.getparam( i ); string nameWithoutSuffix; @@ -1599,7 +1571,7 @@ static IECore::ConstCompoundDataPtr metadataGetter( const std::string &shaderNam const OSLQuery::Parameter *basisParameter; const OSLQuery::Parameter *countParameter; - // If this parameter is part of a spline, register the metadata onto the spline plug + // If this parameter is part of a ramp, register the metadata onto the ramp plug if( !findSplineParametersFromPositions( shaderName, query, positionsParameter, nameWithoutSuffix, valuesParameter, basisParameter, countParameter, parametersAlreadyProcessed ) ) { continue; diff --git a/src/GafferRenderMan/RenderManShader.cpp b/src/GafferRenderMan/RenderManShader.cpp index 7c46ccd797..73cb0969de 100644 --- a/src/GafferRenderMan/RenderManShader.cpp +++ b/src/GafferRenderMan/RenderManShader.cpp @@ -43,7 +43,7 @@ #include "Gaffer/CompoundNumericPlug.h" #include "Gaffer/NumericPlug.h" #include "Gaffer/PlugAlgo.h" -#include "Gaffer/SplinePlug.h" +#include "Gaffer/RampPlug.h" #include "Gaffer/StringPlug.h" #include "IECore/SearchPath.h" @@ -285,8 +285,8 @@ Gaffer::Plug *loadParameter( const boost::property_tree::ptree ¶meter, Plug Plug *candidatePlug; if( parameter.get( ".isDynamicArray", "0" ) == "1" ) { - // Spline parameters are handled separately in findSplinePlugFromPositionsParameter, - // leaving very few examples of non-spline array parameters in the + // Ramp parameters are handled separately in findRampPlugFromPositionsParameter, + // leaving very few examples of non-ramp array parameters in the // standard RenderMan shaders. All non-spline arrays seem to be used to // provide an array of connections rather than values - see // `PxrSurface.utilityPattern` for example. So we load as an @@ -360,29 +360,7 @@ Gaffer::Plug *loadParameter( const boost::property_tree::ptree ¶meter, Plug return acquiredPlug.get(); } -SplineDefinitionInterpolation basisFromString( const std::string &basis ) -{ - if( basis == "bspline" ) - { - return SplineDefinitionInterpolationBSpline; - } - else if( basis == "linear" ) - { - return SplineDefinitionInterpolationLinear; - } - else if( basis == "constant" ) - { - return SplineDefinitionInterpolationConstant; - } - else if( basis == "monotonecubic" ) - { - return SplineDefinitionInterpolationMonotoneCubic; - } - - return SplineDefinitionInterpolationCatmullRom; -} - -PlugPtr findSplinePlugFromPositionsParameter( +PlugPtr findRampPlugFromPositionsParameter( const std::string& positionName, const boost::property_tree::ptree &positionsParameter, const std::map< std::string, const boost::property_tree::ptree* > ¶meters, Plug::Direction direction, std::unordered_set ¶metersAlreadyProcessed ) @@ -428,7 +406,7 @@ PlugPtr findSplinePlugFromPositionsParameter( { throw IECore::Exception( "Spline _Interpretation not a string parameter: " + basisName ); } - SplineDefinitionInterpolation interpolationDefault = basisFromString( basisParameter.get( ".default", "" ) ); + std::string interpolationString = basisParameter.get( ".default", "" ); // In the PRMan spline convention, there is a 4th parameter, which is just an integer matching the // length of the arrays. In the PRMan OSL shaders, a there is an example where the default @@ -526,52 +504,46 @@ PlugPtr findSplinePlugFromPositionsParameter( ); } - SplineDefinitionfColor3f defaultValue; - defaultValue.interpolation = interpolationDefault; - for( unsigned int i = 0; i < positionsDefault.size(); i++ ) + std::vector< Imath::Color3f > values; + for( unsigned int i = 0; i < valueTokens.size() / 3; i++ ) { - defaultValue.points.insert( - std::pair{ positionsDefault[i], - Imath::Color3f( - boost::lexical_cast( valueTokens[3*i] ), - boost::lexical_cast( valueTokens[3*i + 1] ), - boost::lexical_cast( valueTokens[3*i + 2 ] ) - ) - } + values.push_back( + Imath::Color3f( + boost::lexical_cast( valueTokens[3*i] ), + boost::lexical_cast( valueTokens[3*i + 1] ), + boost::lexical_cast( valueTokens[3*i + 2 ] ) + ) ); } - defaultValue.trimEndPoints(); - - return new SplinefColor3fPlug( baseName, direction, defaultValue , Plug::Default ); + RampfColor3f defaultValue; + defaultValue.fromOSL( interpolationString, positionsDefault, values, baseName ); + return new RampfColor3fPlug( baseName, direction, defaultValue , Plug::Default ); } else { - SplineDefinitionff defaultValue; - defaultValue.interpolation = interpolationDefault; - - for( unsigned int i = 0; i < positionsDefault.size(); i++ ) + std::vector< float > values; + for( unsigned int i = 0; i < valueTokens.size(); i++ ) { - defaultValue.points.insert( - std::pair{ positionsDefault[i], boost::lexical_cast( valueTokens[i] ) } - ); + values.push_back( boost::lexical_cast( valueTokens[i] ) ); } - defaultValue.trimEndPoints(); + Rampff defaultValue; + defaultValue.fromOSL( interpolationString, positionsDefault, values, baseName ); - return new SplineffPlug( baseName, direction, defaultValue , Plug::Default ); + return new RampffPlug( baseName, direction, defaultValue , Plug::Default ); } } void loadParameters( const boost::property_tree::ptree &tree, Plug *parent, const ParameterSet *omit, std::unordered_set &validPlugs ) { - // In order to assemble together the parameters needed to build a spline, we need to be able to look up + // In order to assemble together the parameters needed to build a ramp, we need to be able to look up // parameters by name. Build a map of all the parameters that we should be building plugs from std::map parameters; std::unordered_set parametersAlreadyProcessed; - std::unordered_map splinePlugs; + std::unordered_map rampPlugs; for( const auto &child : tree ) { @@ -588,25 +560,25 @@ void loadParameters( const boost::property_tree::ptree &tree, Plug *parent, cons } } - // Find the splines + // Find the ramps for( const auto ¶m : parameters ) { - PlugPtr spline; + PlugPtr ramp; try { - spline = findSplinePlugFromPositionsParameter( param.first, *param.second, parameters, parent->direction(), parametersAlreadyProcessed ); + ramp = findRampPlugFromPositionsParameter( param.first, *param.second, parameters, parent->direction(), parametersAlreadyProcessed ); } catch( std::exception &e ) { msg( IECore::Msg::Warning, "RenderManShader::loadShader", - fmt::format( "Error while parsing spline based on \"{}\" : {}", param.first, e.what() ) + fmt::format( "Error while parsing ramp based on \"{}\" : {}", param.first, e.what() ) ); } - if( spline ) + if( ramp ) { - splinePlugs[ param.second ] = spline; + rampPlugs[ param.second ] = ramp; } } @@ -629,11 +601,11 @@ void loadParameters( const boost::property_tree::ptree &tree, Plug *parent, cons continue; } - auto splineIt = splinePlugs.find( &child.second ); - if( splineIt != splinePlugs.end() ) + auto rampIt = rampPlugs.find( &child.second ); + if( rampIt != rampPlugs.end() ) { - parent->addChild( splineIt->second ); - validPlugs.insert( splineIt->second.get() ); + parent->addChild( rampIt->second ); + validPlugs.insert( rampIt->second.get() ); continue; } diff --git a/src/GafferScene/AttributeVisualiser.cpp b/src/GafferScene/AttributeVisualiser.cpp index fa34c64fcb..1c8a3becd3 100644 --- a/src/GafferScene/AttributeVisualiser.cpp +++ b/src/GafferScene/AttributeVisualiser.cpp @@ -66,10 +66,10 @@ AttributeVisualiser::AttributeVisualiser( const std::string &name ) addChild( new FloatPlug( "min", Plug::In, 0.0f ) ); addChild( new FloatPlug( "max", Plug::In, 1.0f ) ); - SplinefColor3fPlug::ValueType rampDefault; - rampDefault.points.insert( SplinefColor3fPlug::ValueType::Point( 1.0f, Color3f( 0.0f, 1.0f, 0.0f ) ) ); - rampDefault.points.insert( SplinefColor3fPlug::ValueType::Point( 0.0f, Color3f( 1.0f, 0.0f, 0.0f ) ) ); - addChild( new SplinefColor3fPlug( "ramp", Plug::In, rampDefault ) ); + RampfColor3fPlug::ValueType rampDefault; + rampDefault.points.insert( RampfColor3fPlug::ValueType::Point( 1.0f, Color3f( 0.0f, 1.0f, 0.0f ) ) ); + rampDefault.points.insert( RampfColor3fPlug::ValueType::Point( 0.0f, Color3f( 1.0f, 0.0f, 0.0f ) ) ); + addChild( new RampfColor3fPlug( "ramp", Plug::In, rampDefault ) ); addChild( new StringPlug( "shaderType", Plug::In, "gl:surface" ) ); addChild( new StringPlug( "shaderName", Plug::In, "Constant" ) ); @@ -120,14 +120,14 @@ const Gaffer::FloatPlug *AttributeVisualiser::maxPlug() const return getChild( g_firstPlugIndex + 3 ); } -Gaffer::SplinefColor3fPlug *AttributeVisualiser::rampPlug() +Gaffer::RampfColor3fPlug *AttributeVisualiser::rampPlug() { - return getChild( g_firstPlugIndex + 4 ); + return getChild( g_firstPlugIndex + 4 ); } -const Gaffer::SplinefColor3fPlug *AttributeVisualiser::rampPlug() const +const Gaffer::RampfColor3fPlug *AttributeVisualiser::rampPlug() const { - return getChild( g_firstPlugIndex + 4 ); + return getChild( g_firstPlugIndex + 4 ); } Gaffer::StringPlug *AttributeVisualiser::shaderTypePlug() @@ -309,8 +309,8 @@ IECore::ConstCompoundObjectPtr AttributeVisualiser::computeProcessedAttributes( color = ( color - min ) / ( max - min ); if( mode == FalseColor ) { - const SplinefColor3f ramp = rampPlug()->getValue().spline(); - color = ramp( color[0] ); + const SplinefColor3f rampEval = rampPlug()->getValue().evaluator(); + color = rampEval( color[0] ); } } diff --git a/src/GafferScene/Shader.cpp b/src/GafferScene/Shader.cpp index 9fb1087d00..03f04d78f0 100644 --- a/src/GafferScene/Shader.cpp +++ b/src/GafferScene/Shader.cpp @@ -46,7 +46,7 @@ #include "Gaffer/PlugAlgo.h" #include "Gaffer/ScriptNode.h" #include "Gaffer/StringPlug.h" -#include "Gaffer/SplinePlug.h" +#include "Gaffer/RampPlug.h" #include "Gaffer/TypedPlug.h" #include "IECoreScene/ShaderNetwork.h" @@ -612,22 +612,22 @@ class Shader::NetworkBuilder } } } - else if( (Gaffer::TypeId)parameter->typeId() == SplineffPlugTypeId ) + else if( (Gaffer::TypeId)parameter->typeId() == RampffPlugTypeId ) { - hashSplineParameterComponentConnections< SplineffPlug >( (const SplineffPlug*)parameter, h ); + hashRampParameterComponentConnections< RampffPlug >( (const RampffPlug*)parameter, h ); } - else if( (Gaffer::TypeId)parameter->typeId() == SplinefColor3fPlugTypeId ) + else if( (Gaffer::TypeId)parameter->typeId() == RampfColor3fPlugTypeId ) { - hashSplineParameterComponentConnections< SplinefColor3fPlug >( (const SplinefColor3fPlug*)parameter, h ); + hashRampParameterComponentConnections< RampfColor3fPlug >( (const RampfColor3fPlug*)parameter, h ); } - else if( (Gaffer::TypeId)parameter->typeId() == SplinefColor4fPlugTypeId ) + else if( (Gaffer::TypeId)parameter->typeId() == RampfColor4fPlugTypeId ) { - hashSplineParameterComponentConnections< SplinefColor4fPlug >( (const SplinefColor4fPlug*)parameter, h ); + hashRampParameterComponentConnections< RampfColor4fPlug >( (const RampfColor4fPlug*)parameter, h ); } } template< typename T > - void hashSplineParameterComponentConnections( const T *parameter, IECore::MurmurHash &h ) + void hashRampParameterComponentConnections( const T *parameter, IECore::MurmurHash &h ) { checkNoShaderInput( parameter->interpolationPlug() ); @@ -691,22 +691,22 @@ class Shader::NetworkBuilder } } } - else if( (Gaffer::TypeId)parameter->typeId() == SplineffPlugTypeId ) + else if( (Gaffer::TypeId)parameter->typeId() == RampffPlugTypeId ) { - addSplineParameterComponentConnections< SplineffPlug >( (const SplineffPlug*) parameter, parameterName, connections ); + addRampParameterComponentConnections< RampffPlug >( (const RampffPlug*) parameter, parameterName, connections ); } - else if( (Gaffer::TypeId)parameter->typeId() == SplinefColor3fPlugTypeId ) + else if( (Gaffer::TypeId)parameter->typeId() == RampfColor3fPlugTypeId ) { - addSplineParameterComponentConnections< SplinefColor3fPlug >( (const SplinefColor3fPlug*)parameter, parameterName, connections ); + addRampParameterComponentConnections< RampfColor3fPlug >( (const RampfColor3fPlug*)parameter, parameterName, connections ); } - else if( (Gaffer::TypeId)parameter->typeId() == SplinefColor4fPlugTypeId ) + else if( (Gaffer::TypeId)parameter->typeId() == RampfColor4fPlugTypeId ) { - addSplineParameterComponentConnections< SplinefColor4fPlug >( (const SplinefColor4fPlug*)parameter, parameterName, connections ); + addRampParameterComponentConnections< RampfColor4fPlug >( (const RampfColor4fPlug*)parameter, parameterName, connections ); } } template< typename T > - void addSplineParameterComponentConnections( const T *parameter, const IECore::InternedString ¶meterName, vector &connections ) + void addRampParameterComponentConnections( const T *parameter, const IECore::InternedString ¶meterName, vector &connections ) { const int n = parameter->numPoints(); std::vector< std::tuple > inputs; @@ -756,58 +756,18 @@ class Shader::NetworkBuilder } } - SplineDefinitionInterpolation interp = (SplineDefinitionInterpolation)parameter->interpolationPlug()->getValue(); - int endPointDupes = 0; - // \todo : Need to duplicate the logic from SplineDefinition::endPointMultiplicity - // John requested an explicit notice that we are displeased by this duplication. - // Possible alternatives to this would be storing SplineDefinitionData instead of SplineData - // in the ShaderNetwork, or moving the handling of endpoint multiplicity inside Splineff - if( interp == SplineDefinitionInterpolationCatmullRom ) - { - endPointDupes = 1; - } - else if( interp == SplineDefinitionInterpolationBSpline ) - { - endPointDupes = 2; - } - else if( interp == SplineDefinitionInterpolationMonotoneCubic ) - { - throw IECore::Exception( - "Cannot support monotone cubic interpolation for splines with inputs, for plug " + parameter->fullName() - ); - } - - for( const auto &[ origIndex, componentSuffix, sourceParameter ] : inputs ) { int index = applySort[ origIndex ]; - int outIndexMin, outIndexMax; - if( index == 0 ) - { - outIndexMin = 0; - outIndexMax = endPointDupes; - } - else if( index == n - 1 ) - { - outIndexMin = endPointDupes + n - 1; - outIndexMax = endPointDupes + n - 1 + endPointDupes; - } - else - { - outIndexMin = outIndexMax = index + endPointDupes; - } - for( int i = outIndexMin; i <= outIndexMax; i++ ) - { - IECore::InternedString inputName = fmt::format( - FMT_COMPILE( "{}[{}].y{}" ), - parameterName.string(), i, componentSuffix - ); - connections.push_back( { - sourceParameter, - { IECore::InternedString(), inputName } - } ); - } + IECore::InternedString inputName = fmt::format( + FMT_COMPILE( "{}[{}].y{}" ), + parameterName.string(), index, componentSuffix + ); + connections.push_back( { + sourceParameter, + { IECore::InternedString(), inputName } + } ); } } diff --git a/src/GafferSceneTest/TestShader.cpp b/src/GafferSceneTest/TestShader.cpp index 5fc62cedeb..d1dca19858 100644 --- a/src/GafferSceneTest/TestShader.cpp +++ b/src/GafferSceneTest/TestShader.cpp @@ -43,7 +43,7 @@ #include "Gaffer/OptionalValuePlug.h" #include "Gaffer/PlugAlgo.h" #include "Gaffer/StringPlug.h" -#include "Gaffer/SplinePlug.h" +#include "Gaffer/RampPlug.h" #include "IECore/Spline.h" @@ -162,7 +162,7 @@ void TestShader::loadShader( const std::string &shaderName, bool keepExistingVal { setupTypedPlug( "i", parametersPlug, 0 ); setupTypedPlug( "c", parametersPlug, Imath::Color3f( 0.f ) ); - setupTypedPlug( "spline", parametersPlug, SplineDefinitionfColor3f() ); + setupTypedPlug( "ramp", parametersPlug, RampfColor3f() ); setupOptionalValuePlug( "optionalString", parametersPlug, new StringPlug() ); setupTypedPlug( "c", outPlug, Imath::Color3f( 0.0f ) ); } diff --git a/src/GafferUIModule/PathListingWidgetBinding.cpp b/src/GafferUIModule/PathListingWidgetBinding.cpp index 03ac186c5d..790a21c535 100644 --- a/src/GafferUIModule/PathListingWidgetBinding.cpp +++ b/src/GafferUIModule/PathListingWidgetBinding.cpp @@ -58,7 +58,7 @@ #include "IECore/PathMatcher.h" #include "IECore/SearchPath.h" #include "IECore/SimpleTypedData.h" -#include "IECore/SplineData.h" +#include "IECore/RampData.h" #include "IECore/TypeTraits.h" #include "boost/algorithm/string/predicate.hpp" @@ -474,8 +474,8 @@ QVariant dataToVariant( const IECore::Data *value, int role ) time_t t = ( d->readable() - from_time_t( 0 ) ).total_seconds(); return QVariant( QDateTime::fromSecsSinceEpoch( t ) ); } - case IECore::SplineffDataTypeId : - case IECore::SplinefColor3fDataTypeId : + case IECore::RampffDataTypeId : + case IECore::RampfColor3fDataTypeId : { // Pass through directly for use in PathListingWidgetItemDelegate. QVariant v; @@ -2251,8 +2251,8 @@ struct DisplayColorCache : public IECorePreview::LRUCacheObject::hash() : IECore::MurmurHash() ) + DisplayGradientCacheGetterKey( const IECore::Data *rampData = nullptr ) + : rampData( rampData ), hash( rampData ? rampData->Object::hash() : IECore::MurmurHash() ) { } @@ -2261,7 +2261,7 @@ struct DisplayGradientCacheGetterKey return hash; } - const IECore::Data *splineData; + const IECore::Data *rampData; const IECore::MurmurHash hash; }; @@ -2273,7 +2273,7 @@ struct DisplayGradientCache : public IECorePreview::LRUCache( [displayTransform] ( const DisplayGradientCacheGetterKey &key, size_t &cost, const IECore::Canceller *canceller ) { cost = 1; - return convert( key.splineData, displayTransform ); + return convert( key.rampData, displayTransform ); }, maxGradients ) @@ -2286,26 +2286,27 @@ struct DisplayGradientCache : public IECorePreview::LRUCachetypeId() ) { - case IECore::SplineffDataTypeId : - return convertTyped( static_cast( data )->readable(), displayTransform ); - case IECore::SplinefColor3fDataTypeId : - return convertTyped( static_cast( data )->readable(), displayTransform ); + case IECore::RampffDataTypeId : + return convertTyped( static_cast( data )->readable(), displayTransform ); + case IECore::RampfColor3fDataTypeId : + return convertTyped( static_cast( data )->readable(), displayTransform ); default : return QBrush(); } } - template - static QBrush convertTyped( const SplineType &spline, const DisplayTransform &displayTransform ) + template + static QBrush convertTyped( const RampType &ramp, const DisplayTransform &displayTransform ) { QLinearGradient gradient( QPoint( 0, 0 ), QPoint( 1, 0 ) ); gradient.setCoordinateMode( QGradient::ObjectMode ); + auto evaluator = ramp.evaluator(); const int numStops = 100; for( int i = 0; i < numStops; ++i ) { float x = (float)i / (float)(numStops - 1); - Imath::Color3f c( spline( x ) ); + Imath::Color3f c( evaluator( x ) ); if( displayTransform ) { c = displayTransform( c ); @@ -2344,7 +2345,7 @@ class PathListingWidgetItemDelegate : public QStyledItemDelegate const QVariant displayData = index.data( Qt::DisplayRole ); if( auto data = displayData.value() ) { - // When we want to render splines, we just pass the data + // When we want to render ramps, we just pass the data // through directly and convert it here. QBrush brush = m_displayGradientCache->get( data.get() ); if( brush.style() != Qt::NoBrush ) diff --git a/src/IECoreArnold/CameraAlgo.cpp b/src/IECoreArnold/CameraAlgo.cpp index 1eb9ae6257..75d307871d 100644 --- a/src/IECoreArnold/CameraAlgo.cpp +++ b/src/IECoreArnold/CameraAlgo.cpp @@ -42,7 +42,7 @@ #include "IECore/MessageHandler.h" #include "IECore/SimpleTypedData.h" -#include "IECore/SplineData.h" +#include "IECore/RampData.h" #include "Imath/ImathFun.h" @@ -75,7 +75,7 @@ const AtString g_focusDistanceArnoldString("focus_distance"); const AtString g_motionStartArnoldString("motion_start"); const AtString g_motionEndArnoldString("motion_end"); -AtVector2 curvePoint( const Splineff::Point &point ) +AtVector2 curvePoint( const Rampff::Point &point ) { // Clamping enforces constraints specified in Arnold docs. // Not likely to be an issue in the X-axis, but in Y it's @@ -88,27 +88,29 @@ AtVector2 curvePoint( const Splineff::Point &point ) void setShutterCurveParameter( AtNode *camera, const IECore::Data *value, const std::string &messageContext ) { - auto *splineData = runTimeCast( value ); - if( !splineData ) + auto *rampData = runTimeCast( value ); + if( !rampData ) { - msg( Msg::Warning, messageContext, fmt::format( "Unsupported value type \"{}\" (expected SplineffData).", value->typeName() ) ); + msg( Msg::Warning, messageContext, fmt::format( "Unsupported value type \"{}\" (expected RampffData).", value->typeName() ) ); return; } AtArray *array; - const Splineff &spline = splineData->readable(); - if( spline.basis == CubicBasisf::linear() ) + const Rampff &ramp = rampData->readable(); + if( ramp.interpolation == IECore::RampInterpolation::Linear ) { - array = AiArrayAllocate( spline.points.size(), 1, AI_TYPE_VECTOR2 ); + array = AiArrayAllocate( ramp.points.size(), 1, AI_TYPE_VECTOR2 ); size_t index = 0; - for( const auto &p : spline.points ) + for( const auto &p : ramp.points ) { AiArraySetVec2( array, index++, curvePoint( p ) ); } } else { + IECore::Splineff eval = ramp.evaluator(); + // Cubic curve, but Arnold only supports linear. Just apply a fixed // sampling for now. From SolidAngle support : "Looking at the code, a // larger number of points in the shutter curve should have negligible @@ -118,7 +120,7 @@ void setShutterCurveParameter( AtNode *camera, const IECore::Data *value, const for( int i = 0; i < numSamples; ++i ) { const float x = (float)i / (float)( numSamples - 1 ); - const float y = spline( x ); + const float y = eval( x ); AiArraySetVec2( array, i, curvePoint( { x, y } ) ); } } diff --git a/src/IECoreArnold/ShaderNetworkAlgo.cpp b/src/IECoreArnold/ShaderNetworkAlgo.cpp index 1b9b26a2ca..cc6060b559 100644 --- a/src/IECoreArnold/ShaderNetworkAlgo.cpp +++ b/src/IECoreArnold/ShaderNetworkAlgo.cpp @@ -46,7 +46,7 @@ #include "IECore/AngleConversion.h" #include "IECore/MessageHandler.h" #include "IECore/SimpleTypedData.h" -#include "IECore/Spline.h" +#include "IECore/Ramp.h" #include "IECore/VectorTypedData.h" #include "boost/algorithm/string/predicate.hpp" diff --git a/src/IECoreDelight/ShaderNetworkAlgo.cpp b/src/IECoreDelight/ShaderNetworkAlgo.cpp index c69fe02e38..12264e58e2 100644 --- a/src/IECoreDelight/ShaderNetworkAlgo.cpp +++ b/src/IECoreDelight/ShaderNetworkAlgo.cpp @@ -45,7 +45,7 @@ #include "IECore/MessageHandler.h" #include "IECore/SearchPath.h" #include "IECore/SimpleTypedData.h" -#include "IECore/SplineData.h" +#include "IECore/RampData.h" #include "IECore/VectorTypedData.h" #include "OSL/oslquery.h" @@ -113,7 +113,14 @@ int basisInt( const std::string &basis ) { return BasisTypes::LINEAR; } - // `SplinePlug` converts from `monotonecubic` to `bezier`, so we'll never get `monotonecubic` + + // Our handling of MonotoneCubic ramps is completely broken currently. We call + // convertToOSLConventions on the shader network as a whole, which converts + // MonotoneCubic curves to bezier, and 3delight doesn't support bezier. If we + // wanted to handle this correctly, we would just need to pass the original + // MonotoneCubic data to 3delight as BasisTypes::MONOTONECUBIC. This would + // require some way for convertToOSLConventions to know to not process + // 3delight shaders ( which use a completely different ramp convention ). return BasisTypes::CATMULLROM; } @@ -1021,7 +1028,7 @@ ShaderNetworkPtr preprocessedNetwork( const ShaderNetwork *shaderNetwork ) // may need to put some extra work into getting 3delight's OSL version here. IECoreScene::ShaderNetworkAlgo::convertToOSLConventions( result.get(), OSL_VERSION ); - // IECoreScene::ShaderNetworkAlgo tries to expand splines according to the correct naming convention + // IECoreScene::ShaderNetworkAlgo tries to expand ramps according to the correct naming convention // ... but 3delight doesn't have a consistent naming convention, and we have to do shader queries of // the original OSL shaders to try and figure out what names to use. convertToOSLConventions doesn't do that, // so it just uses the Gaffer naming convention, and we rename the parameters if we're able to find diff --git a/startup/Gaffer/splinePlugCompatibility.py b/startup/Gaffer/splinePlugCompatibility.py new file mode 100644 index 0000000000..6121632894 --- /dev/null +++ b/startup/Gaffer/splinePlugCompatibility.py @@ -0,0 +1,59 @@ +########################################################################## +# +# Copyright (c) 2025, Image Engine Design Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above +# copyright notice, this list of conditions and the following +# disclaimer. +# +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided with +# the distribution. +# +# * Neither the name of John Haddon nor the names of +# any other contributors to this software may be used to endorse or +# promote products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +########################################################################## + +import Gaffer +import IECore + +Gaffer.SplineDefinitionInterpolation = IECore.RampInterpolation + +Gaffer.SplineDefinitionff = IECore.Rampff +Gaffer.SplineDefinitionfColor3f = IECore.RampfColor3f +Gaffer.SplineDefinitionfColor4f = IECore.RampfColor4f + + +# There are two main places that may need this compatibility config for Ramp*Plug. +# The first is the same as most of our compatibility configs: old Gaffer scripts +# that were saved out with Spline*Plug. +# The second is more obscure: python/Gaffer/ExtensionAlgo.py uses a __nodeTemplate +# that adds a constructor to remove the dynamic flag from children of a Ramp*Plug. +# Any custom nodes that were exported using ExtensionAlgo from Gaffer 1.6 or earlier +# will have the "Spline*Plug" names baked, and will depend on this config. The long +# term plan is to fix it so those Dynamic flags would never be set ... we probably +# shouldn't remove this compatibility until after we sort that out. + +Gaffer.SplineffPlug = Gaffer.RampffPlug +Gaffer.SplinefColor3fPlug = Gaffer.RampfColor3fPlug +Gaffer.SplinefColor4fPlug = Gaffer.RampfColor4fPlug diff --git a/startup/GafferArnold/cameraParameters.py b/startup/GafferArnold/cameraParameters.py index 8d09f47948..03ca705dc1 100644 --- a/startup/GafferArnold/cameraParameters.py +++ b/startup/GafferArnold/cameraParameters.py @@ -53,7 +53,7 @@ "camera:parameter:shutter_curve" : { - "defaultValue" : IECore.SplineffData(), + "defaultValue" : IECore.RampffData(), "label" : "Shutter Curve", "layout:section" : "Arnold", diff --git a/startup/GafferArnoldUI/cameraTweaks.py b/startup/GafferArnoldUI/cameraTweaks.py index 7900f5cbde..ee57f2f6f8 100644 --- a/startup/GafferArnoldUI/cameraTweaks.py +++ b/startup/GafferArnoldUI/cameraTweaks.py @@ -51,10 +51,10 @@ def __shutterCurveTweakCreator() : tweak = Gaffer.TweakPlug( "shutter_curve", - Gaffer.SplineffPlug( - defaultValue = Gaffer.SplineDefinitionff( + Gaffer.RampffPlug( + defaultValue = IECore.Rampff( [ ( 0, 0 ), ( 0.25, 1 ), (0.75, 1 ), ( 1, 0 ) ], - Gaffer.SplineDefinitionInterpolation.Linear + IECore.RampInterpolation.Linear ) ), Gaffer.TweakPlug.Mode.Create From dfe1d95076a6b2e3658758e9b743543fc0acb406 Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Mon, 15 Dec 2025 18:24:47 -0800 Subject: [PATCH 11/11] Remove linux-gcc11-platform23 CI target --- .github/workflows/main.yml | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d36633ca36..f6a702c6e2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -34,7 +34,6 @@ jobs: name: [ linux-gcc11, linux-debug-gcc11, - linux-gcc11-platform23, windows, ] @@ -65,20 +64,6 @@ jobs: sconsCacheMegabytes: 2500 jobs: 4 - - name: linux-gcc11-platform23 - os: ubuntu-24.04 - buildType: RELEASE - publish: false - containerImage: ghcr.io/gafferhq/build/build:3.4.0 - # GitHub container builds run as root. This causes failures for tests that - # assert that filesystem permissions are respected, because root doesn't - # respect permissions. So we run the final test suite as a dedicated - # test user rather than as root. - testRunner: sudo -E -u testUser - sconsCacheMegabytes: 400 - jobs: 4 - dependenciesURL: https://github.com/ImageEngine/cortex/releases/download/10.5.15.3/cortex-10.5.15.3-linux-gcc11.tar.gz - - name: windows os: windows-2022 buildType: RELEASE @@ -305,7 +290,7 @@ jobs: run: | podman run -e CI -e RMANTREE -e GITHUB_WORKSPACE -e GAFFER_BUILD_DIR -v /opt/pixar:/opt/pixar -v $GITHUB_WORKSPACE:$GITHUB_WORKSPACE --mac-address a4:bb:6d:cf:40:7a --shm-size 4g --entrypoint=sh -w $GITHUB_WORKSPACE rockylinux:9.3-minimal -c .github/workflows/main/testGafferRenderMan.sh df -H - if: ${{ env.RMANTREE != '' && runner.os != 'Windows' && matrix.name != 'linux-gcc11-platform23' }} + if: ${{ env.RMANTREE != '' && runner.os != 'Windows' }} - name: Build Docs and Package # Docs builds should be relatively quick. If there is a problem, this