diff --git a/Changes.md b/Changes.md index 46d1f51c6ca..ef0ab9d82b1 100644 --- a/Changes.md +++ b/Changes.md @@ -1,7 +1,15 @@ 1.4.x.x (relative to 1.4.1.0) ======= +Improvements +------------ + +- AttributeQuery, PrimitiveVariableQuery, ContextQuery, OptionQuery, ShaderQuery : Added support for querying arrays of length 1 as their equivalent scalar types. + +API +--- +- PlugAlgo : `setValueFromData()` and `canSetValueFromData()` now support conversion of arrays of length 1 to their equivalent scalar types. 1.4.1.0 (relative to 1.4.0.0) ======= diff --git a/python/GafferSceneTest/PrimitiveVariableQueryTest.py b/python/GafferSceneTest/PrimitiveVariableQueryTest.py index 70e8fcecb77..7a90cbe67da 100644 --- a/python/GafferSceneTest/PrimitiveVariableQueryTest.py +++ b/python/GafferSceneTest/PrimitiveVariableQueryTest.py @@ -689,5 +689,36 @@ def testSerialisation( self ) : self.assertEqual( output["type"].getValue(), dataType.staticTypeName() ) self.assertEqual( output["value"].getValue(), value ) + def testArrayScalarConversion( self ) : + + cube = GafferScene.Cube() + + cubeFilter = GafferScene.PathFilter() + cubeFilter["paths"].setValue( IECore.StringVectorData( [ "/cube" ] ) ) + + primitiveVariables = GafferScene.PrimitiveVariables() + primitiveVariables["in"].setInput( cube["out"] ) + primitiveVariables["filter"].setInput( cubeFilter["out"] ) + + primitiveVariables["primitiveVariables"].addChild( Gaffer.NameValuePlug( "testLengthZero", IECore.IntVectorData() ) ) + primitiveVariables["primitiveVariables"].addChild( Gaffer.NameValuePlug( "testLengthOne", IECore.IntVectorData( [ 2 ] ) ) ) + primitiveVariables["primitiveVariables"].addChild( Gaffer.NameValuePlug( "testLengthTwo", IECore.IntVectorData( [ 3, 3 ] ) ) ) + + query = GafferScene.PrimitiveVariableQuery() + query["scene"].setInput( primitiveVariables["out"] ) + query["location"].setValue( "/cube" ) + query.addQuery( Gaffer.IntPlug( defaultValue = -1 ), "testLengthZero" ) + + self.assertEqual( query["out"][0]["exists"].getValue(), True ) + self.assertTrue( query["out"][0]["value"].getValue(), -1 ) + + query["queries"][0]["name"].setValue( "testLengthOne" ) + self.assertEqual( query["out"][0]["exists"].getValue(), True ) + self.assertTrue( query["out"][0]["value"].getValue(), 2 ) + + query["queries"][0]["name"].setValue( "testLengthTwo" ) + self.assertEqual( query["out"][0]["exists"].getValue(), True ) + self.assertTrue( query["out"][0]["value"].getValue(), -1 ) + if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() diff --git a/python/GafferTest/PlugAlgoTest.py b/python/GafferTest/PlugAlgoTest.py index 2f6997405f5..288218dc812 100644 --- a/python/GafferTest/PlugAlgoTest.py +++ b/python/GafferTest/PlugAlgoTest.py @@ -961,6 +961,43 @@ def testDataConversionsForAllTypes( self ) : self.assertEqual( plug.getValue(), data.value ) self.assertEqual( Gaffer.PlugAlgo.getValueAsData( plug ), data ) + def testSetNumericValueFromVectorData( self ) : + + for plugType in Gaffer.FloatPlug, Gaffer.IntPlug, Gaffer.BoolPlug : + plug = plugType() + for dataType in [ + IECore.HalfVectorData, + IECore.FloatVectorData, + IECore.DoubleVectorData, + IECore.UCharVectorData, + IECore.ShortVectorData, + IECore.UShortVectorData, + IECore.IntVectorData, + IECore.UIntVectorData, + IECore.Int64VectorData, + IECore.UInt64VectorData, + IECore.BoolVectorData, + ] : + with self.subTest( plugType = plugType, dataType = dataType ) : + for value in ( 0, 1 ) : + data = dataType() + # Array length 0, can't set. + self.assertFalse( Gaffer.PlugAlgo.canSetValueFromData( plug, data ) ) + plug.setToDefault() + self.assertFalse( Gaffer.PlugAlgo.setValueFromData( plug, data ) ) + self.assertTrue( plug.isSetToDefault() ) + # Array length 1, can set. + data.append( value ) + self.assertTrue( Gaffer.PlugAlgo.canSetValueFromData( plug, data ) ) + self.assertTrue( Gaffer.PlugAlgo.setValueFromData( plug, data ) ) + self.assertEqual( plug.getValue(), value ) + # Array length > 1, can't set. + data.append( value ) + self.assertFalse( Gaffer.PlugAlgo.canSetValueFromData( plug, data ) ) + plug.setToDefault() + self.assertFalse( Gaffer.PlugAlgo.setValueFromData( plug, data ) ) + self.assertTrue( plug.isSetToDefault() ) + def testDependsOnCompute( self ) : add = GafferTest.AddNode() diff --git a/src/Gaffer/PlugAlgo.cpp b/src/Gaffer/PlugAlgo.cpp index 0dba9763621..c80de408812 100644 --- a/src/Gaffer/PlugAlgo.cpp +++ b/src/Gaffer/PlugAlgo.cpp @@ -49,6 +49,7 @@ #include "Gaffer/TypedObjectPlug.h" #include "Gaffer/ValuePlug.h" +#include "IECore/DataAlgo.h" #include "IECore/SplineData.h" #include "boost/algorithm/string/predicate.hpp" @@ -565,6 +566,17 @@ IECore::DataPtr extractDataFromPlug( const ValuePlug *plug ) namespace { +template +bool setNumericPlugValueFromVectorData( PlugType *plug, const DataType *value ) +{ + if( value->readable().size() == 1 ) + { + plug->setValue( value->readable()[0] ); + return true; + } + return false; +} + template bool setNumericPlugValue( PlugType *plug, const Data *value ) { @@ -606,6 +618,30 @@ bool setNumericPlugValue( PlugType *plug, const Data *value ) case BoolDataTypeId : plug->setValue( static_cast( value )->readable() ); return true; + case HalfVectorDataTypeId : + return setNumericPlugValueFromVectorData( plug, static_cast( value ) ); + case FloatVectorDataTypeId : + return setNumericPlugValueFromVectorData( plug, static_cast( value ) ); + case DoubleVectorDataTypeId : + return setNumericPlugValueFromVectorData( plug, static_cast( value ) ); + case CharVectorDataTypeId : + return setNumericPlugValueFromVectorData( plug, static_cast( value ) ); + case UCharVectorDataTypeId : + return setNumericPlugValueFromVectorData( plug, static_cast( value ) ); + case ShortVectorDataTypeId : + return setNumericPlugValueFromVectorData( plug, static_cast( value ) ); + case UShortVectorDataTypeId : + return setNumericPlugValueFromVectorData( plug, static_cast( value ) ); + case IntVectorDataTypeId : + return setNumericPlugValueFromVectorData( plug, static_cast( value ) ); + case UIntVectorDataTypeId : + return setNumericPlugValueFromVectorData( plug, static_cast( value ) ); + case Int64VectorDataTypeId : + return setNumericPlugValueFromVectorData( plug, static_cast( value ) ); + case UInt64VectorDataTypeId : + return setNumericPlugValueFromVectorData( plug, static_cast( value ) ); + case BoolVectorDataTypeId : + return setNumericPlugValueFromVectorData( plug, static_cast( value ) ); default : return false; } @@ -774,6 +810,19 @@ bool canSetNumericPlugValue( const Data *value ) case UInt64DataTypeId : case BoolDataTypeId : return true; + case HalfVectorDataTypeId : + case FloatVectorDataTypeId : + case DoubleVectorDataTypeId : + case CharVectorDataTypeId : + case UCharVectorDataTypeId : + case ShortVectorDataTypeId : + case UShortVectorDataTypeId : + case IntVectorDataTypeId : + case UIntVectorDataTypeId : + case Int64VectorDataTypeId : + case UInt64VectorDataTypeId : + case BoolVectorDataTypeId : + return IECore::size( value ) == 1; default : return false; }