Skip to content

Commit

Permalink
Merge branch '1.1_maintenance' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
johnhaddon committed Jan 13, 2023
2 parents 86da7fb + 85d7979 commit 4a1c27d
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 31 deletions.
38 changes: 31 additions & 7 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,30 @@ Improvements
- HierarchyView : Inclusions and Exclusions column header icons now update to show when one or more locations have been added to or excluded from the Visible Set [^2].
- Light : Added an enable/disable toggle to the `mute` plug [^2].
- AttributeTweaks : Added `Remove` mode.
- NodeEditor : Added "Promote Value and Switch" context menu item for promoting NameValuePlugs to Boxes [^1].

Fixes
-----

- Viewer [^1] :
- Fixed Default display transform so that it updates correctly when the default is changed via the Preferences dialogue, and when the context changes.
- Fixed drawing of image pixels to the left of the display window.
- 3Delight : Fixed rendering with recent versions of 3Delight, which no longer use the `DL_DISPLAYS_PATH` to search for display drivers.
- Metadata :
- Fixed memory leak.
- Fixed thread safety bug that prevented concurrent access to metadata for the _same_ plug or node from multiple threads.
- Cycles [^1] :
- Fixed custom AOVs not being created properly for SVM shading mode only, OSL is not supported. (#5044).
- Fixed distant light angle is in degrees and not radians.
- Fixed custom AOVs (for SVM shading mode only, Cycles doesn't support custom AOVs in OSL mode) (#5044).
- Fixed units for distant light angle (now degrees and not radians).
- Fixed assignment of `emission` shader. Previously this was being assigned as a `cycles:light` attribute instead of `cycles:surface` (#5058).
- Hid internal shader plugs which shouldn't be exposed to the user (e.g. `surface_mix_weight`).
- ImageViewer : Fixed drawing of pixels to the left of the display window [^1].
- UVInspector : Fixed update delay when changing display transform [^1].
- Random : Fixed GIL management bug which could lead to hangs [^1].
- ShufflePrimitiveVariables, ShuffleAttributes, OptionQuery, PrimitiveVariableQuery, ShaderQuery, ContextQuery, CreateViews, SetVisualiser, OSLImage, OSLObject, OSLCode, Outputs : Fixed bugs which allowed read-only nodes to be edited.
- ShaderTweaks : Fixed `Remove` mode [^1].
- FilterQuery : Fixed bug which prevented the output from updating when the input scene changed (#5066) [^1].
- Arnold : Fixed rendering of `token` enum parameter values loaded from USD [^1].

API
---
Expand Down Expand Up @@ -159,7 +168,7 @@ Build

- Cortex : Updated to version 10.4.3.0.

1.1.x.x (relative to 1.1.6.1)
1.1.7.0 (relative to 1.1.6.1)
=======

Features
Expand All @@ -177,15 +186,27 @@ Improvements
- OSLObject : Added support for attribute substitutions using `<attr:myAttrName>` syntax in string parameters, provided that `useAttributes` is turned on.
- UIEditor : Increased maximum size of the "Button Click Code" editor.

Improvements
------------

- NodeEditor : Added "Promote Value and Switch" context menu item for promoting NameValuePlugs to Boxes.

Fixes
-----

- Viewer :
- Fixed Default display transform so that it updates correctly when the default is changed via the Preferences dialogue, and when the context changes.
- Fixed drawing of image pixels to the left of the display window.
- Cycles :
- Fixed custom AOVs not being created properly for SVM shading mode only, OSL is not supported. (#5044).
- Fixed distant light angle is in degrees and not radians.
- Fixed custom AOVs (for SVM shading mode only, Cycles doesn't support custom AOVs in OSL mode) (#5044).
- Fixed units for distant light angle (now degrees and not radians).
- Fixed assignment of `emission` shader. Previously this was being assigned as a `cycles:light` attribute instead of `cycles:surface` (#5058).
- ImageViewer : Fixed drawing of pixels to the left of the display window.
- Hid internal shader plugs which shouldn't be exposed to the user (e.g. `surface_mix_weight`).
- UVInspector : Fixed update delay when changing display transform.
- Random : Fixed GIL management bug which could lead to hangs.
- ShaderTweaks : Fixed `Remove` mode.
- FilterQuery : Fixed bug which prevented the output from updating when the input scene changed (#5066).
- Arnold : Fixed rendering of `token` enum parameter values loaded from USD.

1.1.6.1 (relative to 1.1.6.0)
=======
Expand Down Expand Up @@ -447,10 +468,13 @@ Breaking Changes
- ImagePlug : Removed unused `viewName` argument from `viewNames()` and `viewNamesHash()` methods.
- StandardAttributes : Removed backwards compatibility for StandardAttributes nodes saved from Gaffer `0.95.0` (May 2014) and earlier. If necessary, resave affected files using a recent Gaffer version.

1.0.6.x (relative to 1.0.6.5)
1.0.6.6 (relative to 1.0.6.5)
=======

- ShaderTweaks : Fixed `Remove` mode.
- FilterQuery : Fixed bug which prevented the output from updating when the input scene changed (#5066).
- Random : Fixed GIL management bug which could lead to hangs.
- Arnold : Fixed rendering of `token` enum parameter values loaded from USD.

1.0.6.5 (relative to 1.0.6.4)
=======
Expand Down
14 changes: 9 additions & 5 deletions include/GafferImageUI/ImageView.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class GAFFERIMAGEUI_API ImageView : public GafferUI::View
const ImageGadget *imageGadget() const;

void setContext( Gaffer::ContextPtr context ) override;
void contextChanged( const IECore::InternedString &name ) override;

using DisplayTransformCreator = std::function<GafferImage::ImageProcessorPtr ()>;

Expand Down Expand Up @@ -184,22 +185,25 @@ class GAFFERIMAGEUI_API ImageView : public GafferUI::View
bool keyPress( const GafferUI::KeyEvent &event );
void preRender();

void insertDisplayTransform();
void updateDisplayTransform();

struct DisplayTransformEntry
{
GafferImage::ImageProcessorPtr displayTransform;
IECoreGL::Shader::SetupPtr shader;
bool shaderDirty = true;
IECore::MurmurHash shaderHash;
bool supportsShader;
};

void setWipeActive( bool active );

using DisplayTransformMap = std::map<std::string, DisplayTransformEntry>;
DisplayTransformMap m_displayTransforms;
DisplayTransformEntry *m_displayTransformAndShader;

void insertDisplayTransform();
void displayTransformPlugDirtied( DisplayTransformEntry *displayTransform );
void updateDisplayTransform();

void setWipeActive( bool active );

IECore::BoolDataPtr m_absoluteValueParameter;
IECore::BoolDataPtr m_clippingParameter;
IECore::Color3fDataPtr m_multiplyParameter;
Expand Down
21 changes: 21 additions & 0 deletions python/GafferSceneTest/FilterQueryTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,5 +167,26 @@ def testNonExistentLocationWithAncestors( self ) :
self.assertEqual( query["ancestorMatch"].getValue(), False )
self.assertEqual( query["closestAncestor"].getValue(), "" )

def testChangingSet( self ) :

sphere = GafferScene.Sphere()
sphere["sets"].setValue( "setA" )

setFilter = GafferScene.SetFilter()
setFilter["setExpression"].setValue( "setA" )

query = GafferScene.FilterQuery()
query["scene"].setInput( sphere["out"] )
query["filter"].setInput( setFilter["out"] )
query["location"].setValue( "/sphere" )

self.assertEqual( query["exactMatch"].getValue(), True )
self.assertEqual( query["closestAncestor"].getValue(), "/sphere" )

sphere["sets"].setValue( "setB" )

self.assertEqual( query["exactMatch"].getValue(), False )
self.assertEqual( query["closestAncestor"].getValue(), "" )

if __name__ == "__main__":
unittest.main()
18 changes: 18 additions & 0 deletions python/GafferSceneTest/ShaderTweaksTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,5 +432,23 @@ def testLocalise( self ) :
colorTweak["enabled"].setValue( False )
self.assertTrue( "surface" not in tweaks["out"].attributes( "/group/plane" ) )

def testRemove( self ) :

light = GafferSceneTest.TestLight()
self.assertIn( "intensity", light["out"].attributes( "/light" )["light"].outputShader().parameters )

pathFilter = GafferScene.PathFilter()
pathFilter["paths"].setValue( IECore.StringVectorData( [ "/light" ] ) )

tweaks = GafferScene.ShaderTweaks()
tweaks["in"].setInput( light["out"] )
tweaks["shader"].setValue( "light" )
tweaks["filter"].setInput( pathFilter["out"] )

tweaks["tweaks"].addChild(
Gaffer.TweakPlug( "intensity", 2.0, mode = Gaffer.TweakPlug.Mode.Remove )
)
self.assertNotIn( "intensity", tweaks["out"].attributes( "/light" )["light"].outputShader().parameters )

if __name__ == "__main__":
unittest.main()
7 changes: 6 additions & 1 deletion python/GafferUI/BoxUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,11 @@ def __upgradeToUseBoxIO( node ) :
def __promote( plug ) :

with Gaffer.UndoScope( plug.ancestor( Gaffer.ScriptNode ) ) :
Gaffer.BoxIO.promote( plug )
promoted = Gaffer.BoxIO.promote( plug )
if isinstance( promoted, Gaffer.NameValuePlug ) :
Gaffer.Metadata.registerValue(
promoted, "nameValuePlugPlugValueWidget:ignoreNamePlug", True
)

def __unpromote( plug ) :

Expand All @@ -311,6 +315,7 @@ def __appendPlugPromotionMenuItems( menuDefinition, plug ) :
Gaffer.ArrayPlug : "Array",
Gaffer.TransformPlug : "Transform",
Gaffer.Transform2DPlug : "Transform",
Gaffer.NameValuePlug : "Value and Switch",
}.get( type( plug.parent() ) )

if ancestorLabel is not None :
Expand Down
18 changes: 18 additions & 0 deletions python/IECoreArnoldTest/ShaderNetworkAlgoTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1007,5 +1007,23 @@ def testConvertUSDRectLightTextureWithColor( self ) :
self.assertEqual( texture.name, "image" )
self.assertEqual( texture.parameters["filename"].value, "myFile.tx" )

def testInternedStringsForEnumParameters( self ) :

network = IECoreScene.ShaderNetwork(
shaders = {
"noiseHandle" : IECoreScene.Shader(
"cell_noise", "ai:surface",
{ "pattern" : IECore.InternedStringData( "worley1" ) }
),
},
output = "noiseHandle"
)

with IECoreArnold.UniverseBlock( writable = True ) as universe :

nodes = IECoreArnold.ShaderNetworkAlgo.convert( network, universe, "test" )
self.assertEqual( len( nodes ), 1 )
self.assertEqual( arnold.AiNodeGetStr( nodes[0], "pattern" ), "worley1" )

if __name__ == "__main__":
unittest.main()
3 changes: 2 additions & 1 deletion src/GafferCycles/SocketHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,8 @@ void setupPlugs( const ccl::NodeType *nodeType, Gaffer::GraphComponent *plugsPar
{
for( const ccl::SocketType &socketType : nodeType->inputs )
{
if( g_socketBlacklist.contains( { nodeType->name, socketType.name } ) )
if( g_socketBlacklist.contains( { nodeType->name, socketType.name } ) ||
( socketType.flags & ccl::SocketType::INTERNAL ) )
{
continue;
}
Expand Down
48 changes: 37 additions & 11 deletions src/GafferImageUI/ImageView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1815,6 +1815,16 @@ void ImageView::setContext( Gaffer::ContextPtr context )
m_imageGadgets[1]->setContext( context );
}

void ImageView::contextChanged( const IECore::InternedString &name )
{
for( auto &[name, displayTransform] : m_displayTransforms )
{
// The values on the OpenColorIOTransform node can contain
// context variable substitutions.
displayTransform.shaderDirty = true;
}
}

void ImageView::plugSet( Gaffer::Plug *plug )
{
if( plug == soloChannelPlug() )
Expand Down Expand Up @@ -2010,25 +2020,29 @@ void ImageView::preRender()
{
viewportGadget()->setPostProcessShader( nullptr );
}
else
else if( !m_displayTransformAndShader->shader || m_displayTransformAndShader->shaderDirty )
{
if( m_displayTransformAndShader->shader == nullptr )
if( !m_displayTransformAndShader->displayTransform )
{
if( !m_displayTransformAndShader->displayTransform )
{
m_displayTransformAndShader->shader = OpenColorIOAlgo::displayTransformToFramebufferShader( nullptr );
}
else
{
const OpenColorIOTransform *ocioTrans = runTimeCast<const OpenColorIOTransform>(
m_displayTransformAndShader->displayTransform.get()
);
m_displayTransformAndShader->shader = OpenColorIOAlgo::displayTransformToFramebufferShader( nullptr );
}
else
{
Context::Scope scope( getContext() );
const OpenColorIOTransform *ocioTrans = runTimeCast<const OpenColorIOTransform>(
m_displayTransformAndShader->displayTransform.get()
);

const IECore::MurmurHash h = ocioTrans->processorHash();
if( h != m_displayTransformAndShader->shaderHash )
{
m_displayTransformAndShader->shader = OpenColorIOAlgo::displayTransformToFramebufferShader(
ocioTrans->processor().get()
);
m_displayTransformAndShader->shaderHash = h;
}
}
m_displayTransformAndShader->shaderDirty = false;

m_displayTransformAndShader->shader->addUniformParameter( "absoluteValue", m_absoluteValueParameter );
m_displayTransformAndShader->shader->addUniformParameter( "clipping", m_clippingParameter );
Expand Down Expand Up @@ -2117,6 +2131,9 @@ void ImageView::insertDisplayTransform()
{
getPreprocessor()->addChild( m_displayTransformAndShader->displayTransform );
m_displayTransformAndShader->displayTransform->inPlug()->setInput( m_imageBeforeColorTransform );
m_displayTransformAndShader->displayTransform->plugDirtiedSignal().connect(
boost::bind( &ImageView::displayTransformPlugDirtied, this, m_displayTransformAndShader )
);
}
}

Expand All @@ -2132,6 +2149,15 @@ void ImageView::insertDisplayTransform()
updateDisplayTransform();
}

void ImageView::displayTransformPlugDirtied( DisplayTransformEntry *displayTransform )
{
displayTransform->shaderDirty = true;
if( displayTransform == m_displayTransformAndShader )
{
viewportGadget()->renderRequestSignal()( viewportGadget() );
}
}

void ImageView::updateDisplayTransform()
{
// Enable the CPU path if necessary
Expand Down
1 change: 1 addition & 0 deletions src/GafferScene/FilterQuery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ void FilterQuery::hash( const Gaffer::ValuePlug *output, const Gaffer::Context *
ScenePlug::PathScope scope( context, &locationPath );
if( scenePlug()->existsPlug()->getValue() )
{
const FilterPlug::SceneScope sceneScope( scope.context(), scenePlug() );
filterPlug()->hash( h );
}
}
Expand Down
13 changes: 11 additions & 2 deletions src/GafferScene/ShaderTweaks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,8 +335,17 @@ bool ShaderTweaks::applyTweaks( IECoreScene::ShaderNetwork *shaderNetwork, Tweak
},
[&parameter, &modifiedShader]( const std::string &valueName, DataPtr newData )
{
modifiedShader.first->second->parameters()[parameter.name] = newData;
return true;
if( newData )
{
modifiedShader.first->second->parameters()[parameter.name] = newData;
return true;
}
else
{
return static_cast<bool>(
modifiedShader.first->second->parameters().erase( parameter.name )
);
}
},
missingMode
)
Expand Down
1 change: 1 addition & 0 deletions src/GafferSceneUI/UVView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@ void UVView::plugSet( const Gaffer::Plug *plug )
if( plug == displayTransformPlug() )
{
m_displayTransformDirty = true;
viewportGadget()->renderRequestSignal()( viewportGadget() );
}
}

Expand Down
15 changes: 11 additions & 4 deletions src/IECoreArnold/ParameterAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,21 @@ void setParameterInternal( AtNode *node, AtString name, int parameterType, bool
}
break;
case AI_TYPE_ENUM :
// Arnold supports setting enums with either the integer index or the string name

// First try getting an integer, but don't warn if it fails
// Arnold supports setting enums with either the integer index
// or the string name. First try getting an integer, but don't
// warn if it fails.
if( const IntData *data = runTimeCast<const IntData>( value ) )
{
AiNodeSetInt( node, name, data->readable() );
}
// Then try getting a string, with the usual warning if nothing has been found yet
// Maya exports enum parameters as `TfToken`, which get loaded
// as InternedStringData by Cortex. Try that next.
else if( const InternedStringData *data = runTimeCast<const InternedStringData>( value ) )
{
AiNodeSetStr( node, name, AtString( data->readable().c_str() ) );
}
// Then try getting a string, with the usual warning if nothing
// has been found yet.
else if( const StringData *data = dataCast<StringData>( name, value ) )
{
AiNodeSetStr( node, name, AtString( data->readable().c_str() ) );
Expand Down

0 comments on commit 4a1c27d

Please sign in to comment.