From 41d91eb7532f9ddc31c44078e912ad40217af4da Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Mon, 3 Nov 2025 18:52:34 -0800 Subject: [PATCH 01/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 3b38357e327..f7c4aa4289b 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 f4be8a6c02ebfa6ea6a19d5fd91e6c59f83e034c Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Wed, 26 Nov 2025 09:58:14 -0800 Subject: [PATCH 02/11] IECoreDelight::ShaderNetworkAlgo : Use convertToOSLConventions Previously, connections to color components in OSL shaders would fail in 3Delight --- src/IECoreDelight/ShaderNetworkAlgo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/IECoreDelight/ShaderNetworkAlgo.cpp b/src/IECoreDelight/ShaderNetworkAlgo.cpp index f588f3624fa..305722b62b6 100644 --- a/src/IECoreDelight/ShaderNetworkAlgo.cpp +++ b/src/IECoreDelight/ShaderNetworkAlgo.cpp @@ -1014,11 +1014,11 @@ ShaderNetworkPtr preprocessedNetwork( const ShaderNetwork *shaderNetwork ) { ShaderNetworkPtr result = shaderNetwork->copy(); - IECoreScene::ShaderNetworkAlgo::expandSplines( result.get() ); + 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 661a10d5260698bf15710269fb931c2eebdc7033 Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 25 Nov 2025 15:07:31 -0800 Subject: [PATCH 03/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 231f80537f6..d306c7da19e 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 9617277e5b1..8c1c45307f0 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 43bfb2a1b94feed102d5e18053ae3ffce0ebefc6 Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 25 Nov 2025 15:19:06 -0800 Subject: [PATCH 04/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 27838729200..dd601b6d780 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 0e85aa99dd76973302f1feae4a64d777e758c7c5 Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 18 Nov 2025 15:39:43 -0800 Subject: [PATCH 05/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 f392ea489d8..1b9b26a2cae 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 3e0ab8d664b7936acb577331be2ff376ecab535e Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 25 Nov 2025 15:37:24 -0800 Subject: [PATCH 06/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 7be2f2d4f3d..abd8f4e85f3 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 a3bb59a5fa77de8736d119a9f9dced910d53912a Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 28 Oct 2025 15:52:23 -0700 Subject: [PATCH 07/11] SplinePlug : Remove old compatibility config --- python/GafferTest/ExpressionTest.py | 4 +- startup/Gaffer/splinePlugCompatibility.py | 114 ---------------------- 2 files changed, 2 insertions(+), 116 deletions(-) delete mode 100644 startup/Gaffer/splinePlugCompatibility.py diff --git a/python/GafferTest/ExpressionTest.py b/python/GafferTest/ExpressionTest.py index d023cbe9db4..26b3492fa31 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 7da6ffd46a3..00000000000 --- 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 7c205cb7e01fc6d0543fd1c724613267804aa4f1 Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Wed, 19 Nov 2025 16:03:39 -0800 Subject: [PATCH 08/11] IECoreArnold : Fix crash if converting to ArnoldShader throws --- src/IECoreArnold/Renderer.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/IECoreArnold/Renderer.cpp b/src/IECoreArnold/Renderer.cpp index 275e7a069ed..69a52e95883 100644 --- a/src/IECoreArnold/Renderer.cpp +++ b/src/IECoreArnold/Renderer.cpp @@ -1075,16 +1075,25 @@ class ShaderCache : public IECore::RefCounted Cache::accessor writeAccessor; if( m_cache.insert( writeAccessor, h ) ) { - const std::string nameFormat = "shader:{shaderHandle}:" + writeAccessor->first.toString(); - if( hSubst != IECore::MurmurHash() ) + try { - IECoreScene::ShaderNetworkPtr substitutedShader = shader->copy(); - ShaderNetworkAlgo::applySubstitutions( substitutedShader.get(), attributeName, attributes ); - writeAccessor->second = new ArnoldShader( substitutedShader.get(), m_nodeDeleter, m_universe, nameFormat, m_parentNode ); + const std::string nameFormat = "shader:{shaderHandle}:" + writeAccessor->first.toString(); + if( hSubst != IECore::MurmurHash() ) + { + IECoreScene::ShaderNetworkPtr substitutedShader = shader->copy(); + ShaderNetworkAlgo::applySubstitutions( substitutedShader.get(), attributeName, attributes ); + writeAccessor->second = new ArnoldShader( substitutedShader.get(), m_nodeDeleter, m_universe, nameFormat, m_parentNode ); + } + else + { + writeAccessor->second = new ArnoldShader( shader, m_nodeDeleter, m_universe, nameFormat, m_parentNode ); + } } - else + catch( ... ) { - writeAccessor->second = new ArnoldShader( shader, m_nodeDeleter, m_universe, nameFormat, m_parentNode ); + // Make sure we don't leave empty entries in the cache + m_cache.erase( writeAccessor ); + throw; } } return writeAccessor->second; From a31f63a168d59788a7f339ed21c1d2ed2a1fe382 Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 28 Oct 2025 16:39:45 -0700 Subject: [PATCH 09/11] Use IECore::Ramp - rename all spline stuff that is now ramps --- include/Gaffer/{SplinePlug.h => RampPlug.h} | 112 +--- 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 | 6 +- python/GafferImageTest/SamplerTest.py | 2 +- python/GafferOSLTest/OSLCodeTest.py | 12 +- .../GafferOSLTest/OSLExpressionEngineTest.py | 2 +- python/GafferOSLTest/OSLImageTest.py | 32 +- python/GafferOSLTest/OSLShaderTest.py | 114 ++-- python/GafferOSLTest/ShadingEngineTest.py | 13 +- .../shaders/PxrSplineParameters.osl | 2 +- python/GafferOSLUI/OSLCodeUI.py | 18 +- python/GafferOSLUI/OSLShaderUI.py | 2 +- python/GafferOSLUITest/OSLShaderUITest.py | 8 +- .../RenderManShaderTest.py | 13 +- python/GafferSceneTest/ImageScatterTest.py | 2 +- python/GafferSceneTest/ImageToPointsTest.py | 8 +- python/GafferSceneTest/ShaderTest.py | 18 +- 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 | 28 +- python/GafferTest/TestCase.py | 2 +- python/GafferTest/__init__.py | 2 +- python/GafferUI/ColorSwatchPlugValueWidget.py | 2 +- python/GafferUI/RampPlugValueWidget.py | 134 +++- .../{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/IECoreDelightTest/RendererTest.py | 52 +- src/Gaffer/Plug.cpp | 2 +- src/Gaffer/PlugAlgo.cpp | 12 +- src/Gaffer/RampPlug.cpp | 357 +++++++++++ src/Gaffer/Reference.cpp | 28 +- src/Gaffer/SplinePlug.cpp | 596 ------------------ src/Gaffer/ValuePlug.cpp | 2 +- src/GafferBindings/ValuePlugBinding.cpp | 2 +- .../IECoreCyclesPreview/ShaderNetworkAlgo.cpp | 10 +- .../IECoreCyclesPreview/SocketAlgo.cpp | 22 +- src/GafferCycles/SocketHandler.cpp | 22 +- src/GafferImage/Ramp.cpp | 18 +- src/GafferModule/GafferModule.cpp | 4 +- ...inePlugBinding.cpp => RampPlugBinding.cpp} | 103 +-- ...{SplinePlugBinding.h => RampPlugBinding.h} | 2 +- src/GafferOSL/OSLCode.cpp | 8 +- src/GafferOSL/OSLShader.cpp | 141 ++--- src/GafferRenderMan/RenderManShader.cpp | 72 +-- src/GafferScene/AttributeVisualiser.cpp | 20 +- src/GafferScene/Shader.cpp | 86 +-- src/GafferSceneTest/TestShader.cpp | 4 +- .../PathListingWidgetBinding.cpp | 31 +- src/IECoreArnold/CameraAlgo.cpp | 20 +- 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 +- 66 files changed, 1084 insertions(+), 1618 deletions(-) rename include/Gaffer/{SplinePlug.h => RampPlug.h} (50%) rename python/GafferTest/{SplinePlugTest.py => RampPlugTest.py} (66%) rename python/GafferUI/{SplineWidget.py => RampWidget.py} (88%) 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} (63%) rename src/GafferModule/{SplinePlugBinding.h => RampPlugBinding.h} (98%) create mode 100644 startup/Gaffer/splinePlugCompatibility.py diff --git a/include/Gaffer/SplinePlug.h b/include/Gaffer/RampPlug.h similarity index 50% rename from include/Gaffer/SplinePlug.h rename to include/Gaffer/RampPlug.h index 3bf7f530b6b..049685b4910 100644 --- a/include/Gaffer/SplinePlug.h +++ b/include/Gaffer/RampPlug.h @@ -41,98 +41,22 @@ #include "Gaffer/PlugType.h" #include "Gaffer/TypedPlug.h" -#include "IECore/Spline.h" +#include "IECore/Ramp.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. +/// The RampPlug allows the user to manipulate an IECore::Ramp, which is +/// a simple curve representation with a list of control points and an +/// interpolations. // /// 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 +class GAFFER_API RampPlug : public ValuePlug { public : @@ -141,15 +65,15 @@ class GAFFER_API SplinePlug : public ValuePlug using XPlugType = typename PlugType::Type; using YPlugType = typename PlugType::Type; - GAFFER_PLUG_DECLARE_TEMPLATE_TYPE( SplinePlug, ValuePlug ); + GAFFER_PLUG_DECLARE_TEMPLATE_TYPE( RampPlug, ValuePlug ); - explicit SplinePlug( - const std::string &name = defaultName(), + explicit RampPlug( + const std::string &name = defaultName(), Direction direction=In, const T &defaultValue = T(), unsigned flags = Default ); - ~SplinePlug() override; + ~RampPlug() override; /// Implemented to only accept children which are suitable for use as points /// in the spline. @@ -195,16 +119,12 @@ class GAFFER_API SplinePlug : public ValuePlug T m_defaultValue; }; -using SplineDefinitionff = SplineDefinition; -using SplineDefinitionfColor3f = SplineDefinition; -using SplineDefinitionfColor4f = SplineDefinition; - -using SplineffPlug = SplinePlug; -using SplinefColor3fPlug = SplinePlug; -using SplinefColor4fPlug = SplinePlug; +using RampffPlug = RampPlug; +using RampfColor3fPlug = RampPlug; +using RampfColor4fPlug = RampPlug; -IE_CORE_DECLAREPTR( SplineffPlug ); -IE_CORE_DECLAREPTR( SplinefColor3fPlug ); -IE_CORE_DECLAREPTR( SplinefColor4fPlug ); +IE_CORE_DECLAREPTR( RampffPlug ); +IE_CORE_DECLAREPTR( RampfColor3fPlug ); +IE_CORE_DECLAREPTR( RampfColor4fPlug ); } // namespace Gaffer diff --git a/include/Gaffer/TypeIds.h b/include/Gaffer/TypeIds.h index afeab8892e4..52d9daf6cd2 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 f06e082d39e..25b33104dfe 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 df9841a0568..9492ce93900 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 9ec596d83ac..4c8f20804d7 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 09dd858d6d9..542249590ef 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 59fd560dc09..07dc53bedc4 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 75217f5e544..65732575d3d 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 ) ) diff --git a/python/GafferImageTest/SamplerTest.py b/python/GafferImageTest/SamplerTest.py index 8577cdc9b45..194aef2c36f 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 5191a1e0d42..273b212f1fc 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 870496976e4..d7cd311acc0 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 08d54ed24ef..b5dd6d972bd 100644 --- a/python/GafferOSLTest/OSLImageTest.py +++ b/python/GafferOSLTest/OSLImageTest.py @@ -872,7 +872,7 @@ def testOSLSplineMatch( self ): # 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( + IECore.RampfColor3f( ( ( 0.1580, imath.Color3f( 0.71, 0.21, 0.39 ) ), ( 0.2249, imath.Color3f( 0, 0.30, 0 ) ), @@ -884,7 +884,7 @@ 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 ) ) @@ -893,9 +893,9 @@ def testOSLSplineMatch( self ): oslImage["channels"]["channel"]["value"].setInput( colorSpline["out"]["c"] ) oslImage["defaultFormat"].setValue( GafferImage.Format( 3000, 64, 1.000 ) ) - for i in Gaffer.SplineDefinitionInterpolation.names.values(): + for i in IECore.RampInterpolation.names.values(): colorSpline["parameters"]["spline"]["interpolation"].setValue( i ) - cortexSpline = colorSpline["parameters"]["spline"].getValue().spline() + cortexSpline = colorSpline["parameters"]["spline"].getValue().evaluator() samplers = [ GafferImage.Sampler( oslImage["out"], c, imath.Box2i( imath.V2i( 0 ), imath.V2i( 3000, 1 ) ) ) for c in [ "R", "G", "B" ] @@ -918,7 +918,7 @@ def testOSLSplineConnections( self ): 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'].setValue( IECore.Rampff( ( ( 1/8, 0 ), ( 3/8, 0 ), ( 5/8, 1 ), ( 7/8, 1 )), IECore.RampInterpolation.Constant ) ) floatSpline["parameters"]["spline"]["p1"]["y"].setInput( invertU["out"]["out"] ) floatSpline["parameters"]["spline"]["p2"]["y"].setInput( g["out"]["globalU"] ) @@ -936,17 +936,17 @@ 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 ) + floatSpline["parameters"]["spline"]["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 ) + floatSpline["parameters"]["spline"]["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 ) + floatSpline["parameters"]["spline"]["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" ): + floatSpline["parameters"]["spline"]["interpolation"].setValue( IECore.RampInterpolation.MonotoneCubic ) + with self.assertRaisesRegex( Exception, "Cannot connect adaptors to ramp when using monotoneCubic interpolation"): testEval( "R" ) # Make connections to outermost control points ( this will require duplicating connections to the @@ -956,17 +956,17 @@ def testEval( channelName ): floatSpline["parameters"]["spline"]["p2"]["y"].setInput( None ) floatSpline["parameters"]["spline"]["p3"]["y"].setInput( g["out"]["globalU"] ) - floatSpline["parameters"]["spline"]["interpolation"].setValue( Gaffer.SplineDefinitionInterpolation.Constant ) + floatSpline["parameters"]["spline"]["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 ) + floatSpline["parameters"]["spline"]["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 ) + floatSpline["parameters"]["spline"]["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 ) + floatSpline["parameters"]["spline"]["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 @@ -974,12 +974,12 @@ def testEval( channelName ): colorSpline.loadShader( "Pattern/ColorSpline" ) colorSpline["parameters"]["x"].setInput( g["out"]["globalV"] ) - colorSpline['parameters']['spline'].setValue( Gaffer.SplineDefinitionfColor3f( + colorSpline['parameters']['spline'].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() diff --git a/python/GafferOSLTest/OSLShaderTest.py b/python/GafferOSLTest/OSLShaderTest.py index 91bad1b2a1b..dbbb172c5fd 100644 --- a/python/GafferOSLTest/OSLShaderTest.py +++ b/python/GafferOSLTest/OSLShaderTest.py @@ -697,9 +697,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(), [ @@ -711,9 +711,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(), [ @@ -727,9 +727,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(), [ @@ -739,9 +739,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(), [ @@ -754,29 +754,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 ) ) @@ -791,9 +785,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(), [ @@ -827,9 +821,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(), [ @@ -839,9 +833,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(), [ @@ -853,9 +847,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(), [ @@ -872,9 +866,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(), [ @@ -886,9 +880,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(), [ @@ -898,22 +892,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 ) : @@ -942,9 +936,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(), [ @@ -954,9 +948,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(), [ @@ -968,17 +962,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 ) ) @@ -1008,17 +1002,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 ): @@ -1217,7 +1211,7 @@ 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 ) + splineValue = 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 ) diff --git a/python/GafferOSLTest/ShadingEngineTest.py b/python/GafferOSLTest/ShadingEngineTest.py index e74c2149df2..d4a872225dc 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 b89c5bb3036..982aae5d077 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 0258f973eb3..4351dd35a93 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 1df01ecefd9..be3c7eab600 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 64c297e2128..a8b2e7dff41 100644 --- a/python/GafferOSLUITest/OSLShaderUITest.py +++ b/python/GafferOSLUITest/OSLShaderUITest.py @@ -97,20 +97,20 @@ def testSplineParameterUserDefaults( self ) : Gaffer.Metadata.registerValue( "osl:shader:Pattern/ColorSpline:spline.interpolation", "userDefault", - Gaffer.SplineDefinitionInterpolation.Linear + Gaffer.RampInterpolation.Linear ) s = GafferOSL.OSLShader() s.loadShader( "Pattern/ColorSpline" ) Gaffer.NodeAlgo.applyUserDefaults( s ) - self.assertEqual( s["parameters"]["spline"]["interpolation"].getValue(), Gaffer.SplineDefinitionInterpolation.Linear ) + self.assertEqual( s["parameters"]["spline"]["interpolation"].getValue(), Gaffer.RampInterpolation.Linear ) Gaffer.Metadata.registerValue( "osl:shader:Pattern/ColorSpline:spline.interpolation", "userDefault", - Gaffer.SplineDefinitionInterpolation.MonotoneCubic + Gaffer.RampInterpolation.MonotoneCubic ) Gaffer.NodeAlgo.applyUserDefaults( s ) - self.assertEqual( s["parameters"]["spline"]["interpolation"].getValue(), Gaffer.SplineDefinitionInterpolation.MonotoneCubic ) + self.assertEqual( s["parameters"]["spline"]["interpolation"].getValue(), Gaffer.RampInterpolation.MonotoneCubic ) def testActivatorMetadata( self ) : diff --git a/python/GafferRenderManTest/RenderManShaderTest.py b/python/GafferRenderManTest/RenderManShaderTest.py index 86ea44f59bb..0138ca2ef12 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 03a2e8a1053..51f84ef1f16 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"] ) diff --git a/python/GafferSceneTest/ImageToPointsTest.py b/python/GafferSceneTest/ImageToPointsTest.py index 72ab028e5c8..b825d450f5c 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 a6ebd6223be..494af9e190c 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 ) ), "spline" : IECore.RampfColor3fData() } ) ) def testDetectCyclicConnections( self ) : @@ -637,7 +637,7 @@ def testSpline( self ) : network = n1.attributes()["test:surface"] - self.assertEqual( network.shaders()["n1"].parameters["spline"], IECore.SplinefColor3fData() ) + self.assertEqual( network.shaders()["n1"].parameters["spline"], IECore.RampfColor3fData() ) n1["parameters"]["spline"].addPoint() n1["parameters"]["spline"].addPoint() @@ -650,12 +650,10 @@ def testSpline( self ) : 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 ) @@ -683,7 +681,7 @@ def testSpline( self ) : n1["parameters"]["spline"]["p1"]["x"].setInput( None ) - n1["parameters"]["spline"]["interpolation"].setValue( Gaffer.SplineDefinitionInterpolation.Linear ) + n1["parameters"]["spline"]["interpolation"].setValue( IECore.RampInterpolation.Linear ) network = n1.attributes()["test:surface"] self.assertEqual( @@ -693,7 +691,7 @@ def testSpline( self ) : ] ) - n1["parameters"]["spline"]["interpolation"].setValue( Gaffer.SplineDefinitionInterpolation.MonotoneCubic ) + n1["parameters"]["spline"]["interpolation"].setValue( IECore.RampInterpolation.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"] diff --git a/python/GafferSceneUI/CameraQueryUI.py b/python/GafferSceneUI/CameraQueryUI.py index 83f995b273a..52297e39bf6 100644 --- a/python/GafferSceneUI/CameraQueryUI.py +++ b/python/GafferSceneUI/CameraQueryUI.py @@ -386,8 +386,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 47bc8c48838..616aec3e3c9 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 26b3492fa31..3a078ed9d41 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 889cb320f88..3cd0760be00 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["spline"] = 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 648e8761b04..120c0434392 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 24261480904..b9a0a09148c 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( + spline = 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=spline ) 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( + spline = 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=spline ) 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 5a7514ac1a4..bfe9c98c983 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( + 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,16 +1561,16 @@ 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. + # RampPlugs must add plugs to represent points. defaultValue = splines[i] otherValue = splines[(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"]["spline"] = Gaffer.RampffPlug( defaultValue = defaultValue, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) if nonDefaultAtExport : script["box"]["spline"].setValue( otherValue ) script["box"].exportForReference( fileName ) @@ -1619,21 +1619,21 @@ def testSplinePlug( self ) : self.assertEqual( script["reference"]["spline"].defaultValue(), otherValue ) self.assertTrue( script["reference"]["spline"].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,7 +1642,7 @@ def testSplinePlugUpgradeDefault( self ) : ( 0, 0 ), ( 0, 0 ), ), - Gaffer.SplineDefinitionInterpolation.Linear + IECore.RampInterpolation.Linear ) fileName = self.temporaryDirectory() / "test.grf" @@ -1651,7 +1651,7 @@ def testSplinePlugUpgradeDefault( self ) : # Export a box with a spline on it script["box"] = Gaffer.Box() - script["box"]["spline"] = Gaffer.SplineffPlug( defaultValue = defaultOne, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) + script["box"]["spline"] = 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 diff --git a/python/GafferTest/TestCase.py b/python/GafferTest/TestCase.py index 5d60a5eab56..c4b29e83598 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 ccabca13cff..f95b0954319 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 10d0ea6de4a..ad86ae1c1be 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 13c4584765c..7921566befb 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,121 @@ # ########################################################################## -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.__splineWidget = GafferUI.RampWidget() + + 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.RampfColor3fPlug, Gaffer.RampfColor4fPlug ) ) : + self.__splineWidget.setDrawMode( GafferUI.RampWidget.DrawMode.Ramp ) + else : + self.__splineWidget.setDrawMode( GafferUI.RampWidget.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.setRamp( values[0] ) + else : + self.__splineWidget.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,8 +168,8 @@ 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 = GafferUI.RampWidget() + if isinstance( plug, ( Gaffer.RampfColor3fPlug, Gaffer.RampfColor4fPlug ) ) : self.__splineWidget.setDrawMode( self.__splineWidget.DrawMode.Ramp ) else: self.__splineWidget.setDrawMode( self.__splineWidget.DrawMode.Splines ) @@ -140,7 +246,7 @@ def _valuesForUpdate( plugs, auxiliaryPlugs ) : return [ { - "spline" : p.getValue().spline(), + "splineDefinition" : 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 +258,7 @@ def _updateFromValues( self, values, exception ) : assert( len( values ) < 2 ) if len( values ) : - self.__splineWidget.setSpline( values[0]["spline"] ) + self.__splineWidget.setRamp( values[0]["splineDefinition"] ) with Gaffer.Signals.BlockedConnection( self.__positionsChangedConnection ) : self.__slider.setValues( values[0]["positions"] ) @@ -195,11 +301,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 +330,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 88% rename from python/GafferUI/SplineWidget.py rename to python/GafferUI/RampWidget.py index 6f57a6c8269..bff718c82d3 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, splineDefinition=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 splineDefinition == None : + splineDefinition = IECore.Rampff( + [ ( 0, 0 ), ( 0, 0 ), ( 1, 1 ), - ( 1, 1 ), - ) + ( 1, 1 ) + ], + IECore.RampInterpolation.CatmullRom, ) - self.setSpline( spline ) + self.setRamp( splineDefinition ) self._qtWidget().paintEvent = Gaffer.WeakMethod( self.__paintEvent ) - def setSpline( self, spline ) : + def setRamp( self, splineDefinition ) : try : - if spline==self.__spline : + if splineDefinition==self.__splineDefinition : return except : pass - self.__spline = spline + self.__splineDefinition = splineDefinition self.__splinesToDraw = None self.__gradientToDraw = None self._qtWidget().update() - def getSpline( self ) : + def getRamp( self ) : - return self.__spline + return self.__splineDefinition 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.__splineDefinition.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.__splineDefinition.evaluator() + if isinstance( self.__splineDefinition, 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.__splineDefinition.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 a41d05c4b8b..00000000000 --- 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 f4a84c148b0..8872fa55f69 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 188f631afdf..e016b638106 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 6db9fda2ec3..abec4cf2bca 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/IECoreDelightTest/RendererTest.py b/python/IECoreDelightTest/RendererTest.py index f7c4aa4289b..2e74cd2792c 100644 --- a/python/IECoreDelightTest/RendererTest.py +++ b/python/IECoreDelightTest/RendererTest.py @@ -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 ), } ), @@ -1137,14 +1127,14 @@ def testGafferSplineParameters( self ) : "Pattern/ColorSpline", "osl:shader", { - "spline" : IECore.SplinefColor3f( - IECore.CubicBasisf.linear(), + "spline" : 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 ), } ), diff --git a/src/Gaffer/Plug.cpp b/src/Gaffer/Plug.cpp index 5de181e1cdd..5a3a597370d 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 6dc8d7bb248..b9809702e8d 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 00000000000..a393b456814 --- /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 2c5a98234a1..a44631ab4d8 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,13 +643,13 @@ 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 + // the `x/y` children of spline points. See RampPlugSerialiser // for further details of spline serialisation. continue; } diff --git a/src/Gaffer/SplinePlug.cpp b/src/Gaffer/SplinePlug.cpp deleted file mode 100644 index 880658d40be..00000000000 --- 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 fe036e133e9..1df8f495cc1 100644 --- a/src/Gaffer/ValuePlug.cpp +++ b/src/Gaffer/ValuePlug.cpp @@ -1113,7 +1113,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 26bdc9ae6d9..cafe28e9c20 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 407b5210410..30a5114b050 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,8 +189,12 @@ 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 *splineData = runTimeCast( namedParameter.second.get() ) ) { + // \todo : Feels bad that there are no unit tests for this, but currently we don't even bind + // convertGraph() to Python, so I don't really want to go to the work of testing it while + // in the middle of reworking how we handle ramps. + // For OSL, splines are handled by convertToOSLConventions assert( !isOSLShader ); @@ -199,7 +203,7 @@ ccl::ShaderNode *convertWalk( const ShaderNetwork::Parameter &outputParameter, c SocketAlgo::setRampSocket( node, socket, splineData->readable() ); } } - else if( const SplinefColor3fData *splineData = runTimeCast( namedParameter.second.get() ) ) + else if( const RampfColor3fData *splineData = runTimeCast( namedParameter.second.get() ) ) { // For OSL, splines are handled by convertToOSLConventions assert( !isOSLShader ); diff --git a/src/GafferCycles/IECoreCyclesPreview/SocketAlgo.cpp b/src/GafferCycles/IECoreCyclesPreview/SocketAlgo.cpp index c725002b636..351edea5a35 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 afafcf3630b..d569f0fecc5 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 dd601b6d780..beeac7eeab8 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 17f002c855d..28cca002dc0 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 63% rename from src/GafferModule/SplinePlugBinding.cpp rename to src/GafferModule/RampPlugBinding.cpp index 1d06ed38ff9..36ba4a679cd 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 : @@ -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 78f7239189e..adafad34c99 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 fd98307e88b..719841f7460 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 47ab8950ca2..f70f1529a91 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 splinePlugArgumentsFromPositions( 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 ) @@ -1282,7 +1255,7 @@ void loadShaderParameters( const std::string &shaderName, const OSLQuery &query, // processed as part of a spline. std::unordered_set parametersAlreadyProcessed; - std::unordered_map splinePlugArguments; + std::unordered_map splinePlugArguments; for( size_t i = 0; i < query.nparams(); ++i ) { @@ -1351,13 +1324,13 @@ void loadShaderParameters( const std::string &shaderName, const OSLQuery &query, // 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 ) ) + if( std::holds_alternative< RampfColor3f >( splineIt->second.defaultValue ) ) { - plug = loadSplineParameterFromDefault( splineIt->second.name, std::get( splineIt->second.defaultValue ), parent ); + plug = loadRampParameterFromDefault( splineIt->second.name, std::get( splineIt->second.defaultValue ), parent ); } else { - plug = loadSplineParameterFromDefault( splineIt->second.name, std::get( splineIt->second.defaultValue ), parent ); + plug = loadRampParameterFromDefault( splineIt->second.name, std::get( splineIt->second.defaultValue ), parent ); } } else diff --git a/src/GafferRenderMan/RenderManShader.cpp b/src/GafferRenderMan/RenderManShader.cpp index 7c46ccd7971..5dca94d1628 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,7 +285,7 @@ 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, + // Ramp parameters are handled separately in findRampPlugFromPositionsParameter, // leaving very few examples of non-spline 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 @@ -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,40 +504,34 @@ 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 ); } } @@ -594,7 +566,7 @@ void loadParameters( const boost::property_tree::ptree &tree, Plug *parent, cons PlugPtr spline; try { - spline = findSplinePlugFromPositionsParameter( param.first, *param.second, parameters, parent->direction(), parametersAlreadyProcessed ); + spline = findRampPlugFromPositionsParameter( param.first, *param.second, parameters, parent->direction(), parametersAlreadyProcessed ); } catch( std::exception &e ) { diff --git a/src/GafferScene/AttributeVisualiser.cpp b/src/GafferScene/AttributeVisualiser.cpp index fa34c64fcb6..1c8a3becd3f 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 9fb1087d00a..03f04d78f0e 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 5fc62cedebf..64ac9d91094 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( "spline", 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 03ac186c5d3..790a21c5355 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 1eb9ae6257e..491bd6c75fc 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 ); + auto *splineData = runTimeCast( value ); if( !splineData ) { - 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 = splineData->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 1b9b26a2cae..cc6060b5594 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 305722b62b6..5f6f9a0fc9a 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; } @@ -1016,7 +1023,7 @@ ShaderNetworkPtr preprocessedNetwork( const ShaderNetwork *shaderNetwork ) 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 00000000000..61216328940 --- /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 8d09f47948b..03ca705dc19 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 7900f5cbde0..ee57f2f6f84 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 e6d99bd2bedef01a846873118b40ae0abab46f6f Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 25 Nov 2025 14:29:32 -0800 Subject: [PATCH 10/11] Rename ColorRamp and FloatRamp osl shaders --- shaders/Pattern/ColorRamp.osl | 112 +++++++++++++++++++ shaders/Pattern/FloatRamp.osl | 112 +++++++++++++++++++ startup/GafferOSL/shaderNameCompatibility.py | 2 + startup/gui/menus.py | 3 + 4 files changed, 229 insertions(+) create mode 100644 shaders/Pattern/ColorRamp.osl create mode 100644 shaders/Pattern/FloatRamp.osl diff --git a/shaders/Pattern/ColorRamp.osl b/shaders/Pattern/ColorRamp.osl new file mode 100644 index 00000000000..cebd074c9e6 --- /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 splinePositions[] = { 0, 0, 1, 1 }, + color splineValues[] = { 0, 0, 1, 1 }, + string splineBasis = "catmull-rom", + + string direction = "custom" [[ + string help = "Which direction the spline 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 spline coordinate to use when direction is set to Custom.", + string visibleExpression = "direction == \"custom\"", + ]], + point startPosition = 0 [[ + string help = "Determines the start of a Diagonal spline, or the center of a Radial spline.", + int gafferNoduleLayoutVisible = 0, + string visibleExpression = "direction == \"diagonal\" || direction == \"radial\"", + ]], + point endPosition = point( 1, 1, 0 ) [[ + string help = "Determines the end of a Diagonal spline.", + 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 splineCoord; + if( direction == "custom" ) + { + splineCoord = x; + } + else if( direction == "u" ) + { + splineCoord = uv.x; + } + else if( direction == "v" ) + { + splineCoord = uv.y; + } + else if( direction == "diagonal" ) + { + vector disp = endPosition - startPosition; + splineCoord = dot( uv - startPosition, disp ) / dot( disp, disp ); + } + else if( direction == "radial" ) + { + vector disp = endPosition - startPosition; + splineCoord = length( uv - startPosition ) / radius; + } + + c = colorSpline( splinePositions, splineValues, splineBasis, splineCoord ); +} diff --git a/shaders/Pattern/FloatRamp.osl b/shaders/Pattern/FloatRamp.osl new file mode 100644 index 00000000000..b148f0fe686 --- /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 splinePositions[] = { 0, 0, 1, 1 }, + float splineValues[] = { 0, 0, 1, 1 }, + string splineBasis = "catmull-rom", + + string direction = "custom" [[ + string help = "Which direction the spline 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 spline coordinate to use when direction is set to Custom.", + string visibleExpression = "direction == \"custom\"", + ]], + point startPosition = 0 [[ + string help = "Determines the start of a Diagonal spline, or the center of a Radial spline.", + int gafferNoduleLayoutVisible = 0, + string visibleExpression = "direction == \"diagonal\" || direction == \"radial\"", + ]], + point endPosition = point( 1, 1, 0 ) [[ + string help = "Determines the end of a Diagonal spline.", + 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 splineCoord; + if( direction == "custom" ) + { + splineCoord = x; + } + else if( direction == "u" ) + { + splineCoord = uv.x; + } + else if( direction == "v" ) + { + splineCoord = uv.y; + } + else if( direction == "diagonal" ) + { + vector disp = endPosition - startPosition; + splineCoord = dot( uv - startPosition, disp ) / dot( disp, disp ); + } + else if( direction == "radial" ) + { + vector disp = endPosition - startPosition; + splineCoord = length( uv - startPosition ) / radius; + } + + c = floatSpline( splinePositions, splineValues, splineBasis, splineCoord ); +} diff --git a/startup/GafferOSL/shaderNameCompatibility.py b/startup/GafferOSL/shaderNameCompatibility.py index d28b2147c23..8b141a9c38b 100644 --- a/startup/GafferOSL/shaderNameCompatibility.py +++ b/startup/GafferOSL/shaderNameCompatibility.py @@ -48,6 +48,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 : # diff --git a/startup/gui/menus.py b/startup/gui/menus.py index 6d9453bcd3d..9a8048d00aa 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 27c5b35cc734672529519704541252a04a8ab475 Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Tue, 25 Nov 2025 16:05:50 -0800 Subject: [PATCH 11/11] FIX : ColorRamp and FloatRamp : Fix actual default value instead of needing compat --- shaders/Pattern/ColorRamp.osl | 2 +- shaders/Pattern/FloatRamp.osl | 2 +- startup/GafferOSL/shaderNameCompatibility.py | 5 ++- startup/GafferOSLUI/splineUIMetadata.py | 40 -------------------- 4 files changed, 6 insertions(+), 43 deletions(-) delete mode 100644 startup/GafferOSLUI/splineUIMetadata.py diff --git a/shaders/Pattern/ColorRamp.osl b/shaders/Pattern/ColorRamp.osl index cebd074c9e6..b60ab659a2a 100644 --- a/shaders/Pattern/ColorRamp.osl +++ b/shaders/Pattern/ColorRamp.osl @@ -43,7 +43,7 @@ shader ColorRamp color splineValues[] = { 0, 0, 1, 1 }, string splineBasis = "catmull-rom", - string direction = "custom" [[ + string direction = "v" [[ string help = "Which direction the spline 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", diff --git a/shaders/Pattern/FloatRamp.osl b/shaders/Pattern/FloatRamp.osl index b148f0fe686..1adf68af3fc 100644 --- a/shaders/Pattern/FloatRamp.osl +++ b/shaders/Pattern/FloatRamp.osl @@ -43,7 +43,7 @@ shader FloatRamp float splineValues[] = { 0, 0, 1, 1 }, string splineBasis = "catmull-rom", - string direction = "custom" [[ + string direction = "v" [[ string help = "Which direction the spline 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", diff --git a/startup/GafferOSL/shaderNameCompatibility.py b/startup/GafferOSL/shaderNameCompatibility.py index 8b141a9c38b..8c196bb1a40 100644 --- a/startup/GafferOSL/shaderNameCompatibility.py +++ b/startup/GafferOSL/shaderNameCompatibility.py @@ -151,7 +151,10 @@ 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 diff --git a/startup/GafferOSLUI/splineUIMetadata.py b/startup/GafferOSLUI/splineUIMetadata.py deleted file mode 100644 index 55aed82fedf..00000000000 --- 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" )