Skip to content

Commit

Permalink
PlugAlgo : Add array[1] -> scalar conversion
Browse files Browse the repository at this point in the history
This conversion is available in the various query nodes, and is particularly useful when querying attributes and primitive variables from certain DCCs which like to write everything as arrays, even if they make more sense as scalars.
  • Loading branch information
johnhaddon committed Apr 23, 2024
1 parent 325c2a3 commit 5615407
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 1 deletion.
8 changes: 8 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
@@ -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)
=======
Expand Down
33 changes: 32 additions & 1 deletion python/GafferSceneTest/PrimitiveVariableQueryTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
unittest.main()
37 changes: 37 additions & 0 deletions python/GafferTest/PlugAlgoTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
49 changes: 49 additions & 0 deletions src/Gaffer/PlugAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -565,6 +566,17 @@ IECore::DataPtr extractDataFromPlug( const ValuePlug *plug )
namespace
{

template<typename PlugType, typename DataType>
bool setNumericPlugValueFromVectorData( PlugType *plug, const DataType *value )
{
if( value->readable().size() == 1 )
{
plug->setValue( value->readable()[0] );
return true;
}
return false;
}

template<typename PlugType>
bool setNumericPlugValue( PlugType *plug, const Data *value )
{
Expand Down Expand Up @@ -606,6 +618,30 @@ bool setNumericPlugValue( PlugType *plug, const Data *value )
case BoolDataTypeId :
plug->setValue( static_cast<const BoolData *>( value )->readable() );
return true;
case HalfVectorDataTypeId :
return setNumericPlugValueFromVectorData( plug, static_cast<const HalfVectorData *>( value ) );
case FloatVectorDataTypeId :
return setNumericPlugValueFromVectorData( plug, static_cast<const FloatVectorData *>( value ) );
case DoubleVectorDataTypeId :
return setNumericPlugValueFromVectorData( plug, static_cast<const DoubleVectorData *>( value ) );
case CharVectorDataTypeId :
return setNumericPlugValueFromVectorData( plug, static_cast<const CharVectorData *>( value ) );
case UCharVectorDataTypeId :
return setNumericPlugValueFromVectorData( plug, static_cast<const UCharVectorData *>( value ) );
case ShortVectorDataTypeId :
return setNumericPlugValueFromVectorData( plug, static_cast<const ShortVectorData *>( value ) );
case UShortVectorDataTypeId :
return setNumericPlugValueFromVectorData( plug, static_cast<const UShortVectorData *>( value ) );
case IntVectorDataTypeId :
return setNumericPlugValueFromVectorData( plug, static_cast<const IntVectorData *>( value ) );
case UIntVectorDataTypeId :
return setNumericPlugValueFromVectorData( plug, static_cast<const UIntVectorData *>( value ) );
case Int64VectorDataTypeId :
return setNumericPlugValueFromVectorData( plug, static_cast<const Int64VectorData *>( value ) );
case UInt64VectorDataTypeId :
return setNumericPlugValueFromVectorData( plug, static_cast<const UInt64VectorData *>( value ) );
case BoolVectorDataTypeId :
return setNumericPlugValueFromVectorData( plug, static_cast<const BoolVectorData *>( value ) );
default :
return false;
}
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 5615407

Please sign in to comment.