Skip to content

Commit

Permalink
TypedObjectPlugBinding : Add CompoundData->CompoundObject conversion
Browse files Browse the repository at this point in the history
This allows `CompoundObjectPlug.setValue( compoundData )` to work, meaning we can remove the `attributesCompatibility.py` shim that was doing this manually for just `Attributes.extraAttributes`.

What I don't like about this is the mismatch between the C++ and Python APIs : it's still not possible to call `CompoundObjectPlug::setValue( CompoundData )` in C++. And that's also mismatched with `CompoundObjectPlug::setFrom()` which is implemented to allow connections from CompoundDataPlug. Still, it seems like progress compared to the compatibility shim.

The immediate motivation for this is that it's not currently possible to have `userDefault` metadata for a CompoundObjectPlug, because metadata values must all be `Data`. This allows the registation of a CompoundData value which is converted to a CompoundObject when applied to the plug.
  • Loading branch information
johnhaddon committed Sep 6, 2024
1 parent 6a6b20c commit 0723cc3
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 67 deletions.
1 change: 1 addition & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ API
---

- MetadataWidget : Added `NumericMetadataWidget` class.
- CompoundObjectPlug : The Python binding for `setValue()` now accepts CompoundData in addition to CompoundObject.

Build
-----
Expand Down
14 changes: 14 additions & 0 deletions python/GafferTest/TypedObjectPlugTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,20 @@ def testConnectCompoundDataToCompoundObject( self ) :
self.assertEqual( s2["n"]["user"]["compoundObject"].getInput(), s2["n"]["user"]["compoundData"] )
self.assertEqual( s2["n"]["user"]["compoundObject"].getValue(), IECore.CompoundObject( { "a" : IECore.IntData( 10 ) } ) )

def testSetCompoundObjectFromCompoundData( self ) :

data = IECore.CompoundData( { "a" : 10 } )

plug = Gaffer.CompoundObjectPlug()
plug.setValue( data )
self.assertEqual( plug.getValue(), IECore.CompoundObject( { "a" : IECore.IntData( 10 ) } ) )
self.assertFalse( plug.getValue( _copy = False )["a"].isSame( data["a"] ) )

data = IECore.CompoundData( { "b" : 10 } )
plug.setValue( data, _copy = False )
self.assertEqual( plug.getValue(), IECore.CompoundObject( { "b" : IECore.IntData( 10 ) } ) )
self.assertTrue( plug.getValue( _copy = False )["b"].isSame( data["b"] ) )

def testStaticPlugSerialisationWithoutRepr( self ) :

# This exposed a bug not exposed by `testSerialisationWithoutRepr()`. In
Expand Down
43 changes: 43 additions & 0 deletions src/GafferModule/TypedObjectPlugBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,48 @@
// Deliberately avoiding "using namespace" so that we can be sure
// TypedPlugBinding uses full namespace qualification for all names.

namespace
{

// Allows `CompoundObjectPlug.setValue()` to accept CompoundData.
/// \todo Probably belongs in Cortex.
struct CompoundObjectFromCompoundData
{

CompoundObjectFromCompoundData()
{
boost::python::converter::registry::push_back(
&convertible,
&construct,
boost::python::type_id<IECore::CompoundObjectPtr>()
);
}

static void *convertible( PyObject *obj )
{
boost::python::extract<IECore::CompoundDataPtr> e( obj );
if( e.check() )
{
return obj;
}
return nullptr;
}

static void construct( PyObject *obj, boost::python::converter::rvalue_from_python_stage1_data *data )
{
IECore::CompoundDataPtr compoundData = boost::python::extract<IECore::CompoundDataPtr>( obj );
IECore::CompoundObjectPtr compoundObject = new IECore::CompoundObject;
compoundObject->members().insert( compoundData->readable().begin(), compoundData->readable().end() );

void *storage = ((boost::python::converter::rvalue_from_python_storage<IECore::CompoundObjectPtr>*)data)->storage.bytes;
new (storage) IECore::CompoundObjectPtr( compoundObject );
data->convertible = storage;
}

};

} // namespace

void GafferModule::bindTypedObjectPlug()
{
GafferBindings::TypedObjectPlugClass<Gaffer::ObjectPlug>();
Expand All @@ -65,4 +107,5 @@ void GafferModule::bindTypedObjectPlug()
GafferBindings::TypedObjectPlugClass<Gaffer::CompoundObjectPlug>();
GafferBindings::TypedObjectPlugClass<Gaffer::AtomicCompoundDataPlug>();
GafferBindings::TypedObjectPlugClass<Gaffer::PathMatcherDataPlug>();
CompoundObjectFromCompoundData();
}
67 changes: 0 additions & 67 deletions startup/GafferScene/attributesCompatibility.py

This file was deleted.

0 comments on commit 0723cc3

Please sign in to comment.