Skip to content

Commit

Permalink
Merge pull request #6135 from ericmehl/noduleLabelsAlwaysVisible
Browse files Browse the repository at this point in the history
StandardNodeGadget : Persistent nodule labels
  • Loading branch information
johnhaddon authored Nov 22, 2024
2 parents 9833354 + 89154ca commit 6ca6fd7
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 19 deletions.
2 changes: 2 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Improvements
- Increased menu item icon sizes.
- A lock icon is now displayed next to read-only nodes.
- RenderPassEditor : Changed the current render pass indicator to yellow to match other context-related UI elements.
- GraphEditor : Moved "Show Input Connections" and "Show Output Connections" to "Connections" sub-menu and added "Show Input Labels" and "Show Output Labels" items.

Fixes
-----
Expand All @@ -57,6 +58,7 @@ API
- Deprecated `connect()` function. Use `connectToApplication()` instead.
- SceneEditor : Added `editScope()` method.
- Image : Added optional `image` argument to `createSwatch()` static method.
- StandardNodeGadget : Added support for `nodeGadget:inputNoduleLabelsVisible` and `nodeGadget:outputNoduleLabelsVisible` metadata for setting nodule labels always on. If the metadata entry is not set or `False`, labels will be visible only when they are hovered over.

Build
-----
Expand Down
6 changes: 6 additions & 0 deletions include/GafferUI/StandardNodeGadget.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ namespace GafferUI
class PlugAdder;
class NoduleLayout;
class ConnectionCreator;
class StandardNodule;

/// The standard means of representing a Node in a GraphGadget.
/// Nodes are represented as rectangular boxes with the name displayed
Expand Down Expand Up @@ -150,6 +151,7 @@ class GAFFERUI_API StandardNodeGadget : public NodeGadget
bool dragMove( GadgetPtr gadget, const DragDropEvent &event );
bool dragLeave( GadgetPtr gadget, const DragDropEvent &event );
bool drop( GadgetPtr gadget, const DragDropEvent &event );
void noduleAdded( Nodule *nodule );

ConnectionCreator *closestDragDestination( const DragDropEvent &event ) const;

Expand All @@ -164,6 +166,10 @@ class GAFFERUI_API StandardNodeGadget : public NodeGadget
void updateFocusGadgetVisibility();
void updateTextDimming();

friend class StandardNodule;
// Set the visibility for all nodules based on the metadata registered for this node.
void applyNoduleLabelVisibilityMetadata();

IE_CORE_FORWARDDECLARE( ErrorGadget );
ErrorGadget *errorGadget( bool createIfMissing = true );
void error( const Gaffer::Plug *plug, const Gaffer::Plug *source, const std::string &message );
Expand Down
4 changes: 4 additions & 0 deletions include/GafferUI/StandardNodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ class GAFFERUI_API StandardNodule : public Nodule
bool dragEnd( GadgetPtr gadget, const DragDropEvent &event );
bool drop( GadgetPtr gadget, const DragDropEvent &event );

/// \deprecated Use overloaded method without `visible` when setting `visible = true`
/// or `StandardNodeGadget::applyNoduleLabelVisibilityMetadata()` to restore
/// metadata-aware visibility.
void setCompatibleLabelsVisible( const DragDropEvent &event, bool visible );
void setCompatibleLabelsVisible( const DragDropEvent &event );

private :

Expand Down
35 changes: 33 additions & 2 deletions python/GafferUI/GraphEditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ def plugDirectionsWalk( gadget ) :

if Gaffer.Plug.Direction.In in plugDirections :
menuDefinition.append(
"/Show Input Connections",
"/Connections/Show Input Connections",
{
"checkBox" : functools.partial( cls.__getNodeInputConnectionsVisible, graphEditor.graphGadget(), node ),
"command" : functools.partial( cls.__setNodeInputConnectionsVisible, graphEditor.graphGadget(), node ),
Expand All @@ -225,14 +225,34 @@ def plugDirectionsWalk( gadget ) :

if Gaffer.Plug.Direction.Out in plugDirections :
menuDefinition.append(
"/Show Output Connections",
"/Connections/Show Output Connections",
{
"checkBox" : functools.partial( cls.__getNodeOutputConnectionsVisible, graphEditor.graphGadget(), node ),
"command" : functools.partial( cls.__setNodeOutputConnectionsVisible, graphEditor.graphGadget(), node ),
"active" : not readOnly
}
)

if Gaffer.Plug.Direction.In in plugDirections :
menuDefinition.append(
"/Connections/Show Input Labels",
{
"checkBox" : functools.partial( cls.__getNoduleLabelsVisible, node, "input" ),
"command" : functools.partial( cls.__setNoduleLabelsVisible, node, "input" ),
"active" : not readOnly,
}
)

if Gaffer.Plug.Direction.Out in plugDirections :
menuDefinition.append(
"/Connections/Show Output Labels",
{
"checkBox" : functools.partial( cls.__getNoduleLabelsVisible, node, "output" ),
"command" : functools.partial( cls.__setNoduleLabelsVisible, node, "output" ),
"active" : not readOnly,
}
)

## May be used from a slot attached to nodeContextMenuSignal() to install a
# standard menu item for modifying the enabled state of a node.
@classmethod
Expand Down Expand Up @@ -729,6 +749,17 @@ def __setNodeInputConnectionsVisible( cls, graphGadget, node, value ) :
with Gaffer.UndoScope( node.ancestor( Gaffer.ScriptNode ) ) :
graphGadget.setNodeInputConnectionsMinimised( node, not value )

@classmethod
def __getNoduleLabelsVisible( cls, node, direction ) :

return Gaffer.Metadata.value( node, f"nodeGadget:{direction}NoduleLabelsVisible" ) or False

@classmethod
def __setNoduleLabelsVisible( cls, node, direction, value ) :

with Gaffer.UndoScope( node.ancestor( Gaffer.ScriptNode ) ) :
Gaffer.Metadata.registerValue( node, f"nodeGadget:{direction}NoduleLabelsVisible", value )

@classmethod
def __getNodeOutputConnectionsVisible( cls, graphGadget, node ) :

Expand Down
42 changes: 42 additions & 0 deletions python/GafferUITest/StandardNodeGadgetTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,5 +308,47 @@ def assertMinWidth( gadget, minWidth ) :
Gaffer.Metadata.deregisterValue( n, "nodeGadget:minWidth" )
assertMinWidth( g, 10.0 )

def testNoduleLabelVisibility( self ) :

n = Gaffer.Node()
n.addChild( Gaffer.FloatPlug( "fIn", direction = Gaffer.Plug.Direction.In ) )
n.addChild( Gaffer.FloatPlug( "fOut", direction = Gaffer.Plug.Direction.Out ) )
g = GafferUI.StandardNodeGadget( n )

fIn = g.nodule( n["fIn"] )
fOut = g.nodule( n["fOut"] )

self.assertFalse( fIn.getLabelVisible() )
self.assertFalse( fOut.getLabelVisible() )

Gaffer.Metadata.registerValue( Gaffer.Node, "nodeGadget:inputNoduleLabelsVisible", True )
self.assertTrue( fIn.getLabelVisible() )
self.assertFalse( fOut.getLabelVisible() )

Gaffer.Metadata.registerValue( Gaffer.Node, "nodeGadget:outputNoduleLabelsVisible", True )
self.assertTrue( fIn.getLabelVisible() )
self.assertTrue( fOut.getLabelVisible() )

n.addChild( Gaffer.IntPlug( "iIn", direction = Gaffer.Plug.Direction.In ) )
n.addChild( Gaffer.IntPlug( "iOut", direction = Gaffer.Plug.Direction.Out ) )

iIn = g.nodule( n["iIn"] )
iOut = g.nodule( n["iOut"] )

self.assertTrue( iIn.getLabelVisible() )
self.assertTrue( iOut.getLabelVisible() )

Gaffer.Metadata.registerValue( Gaffer.Node, "nodeGadget:inputNoduleLabelsVisible", False )
self.assertFalse( fIn.getLabelVisible() )
self.assertFalse( iIn.getLabelVisible() )
self.assertTrue( fOut.getLabelVisible() )
self.assertTrue( iOut.getLabelVisible() )

Gaffer.Metadata.registerValue( Gaffer.Node, "nodeGadget:outputNoduleLabelsVisible", False )
self.assertFalse( fIn.getLabelVisible() )
self.assertFalse( iIn.getLabelVisible() )
self.assertFalse( fOut.getLabelVisible() )
self.assertFalse( iOut.getLabelVisible() )

if __name__ == "__main__":
unittest.main()
59 changes: 47 additions & 12 deletions src/GafferUI/StandardNodeGadget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,8 @@ static IECore::InternedString g_paddingKey( "nodeGadget:padding" );
static IECore::InternedString g_colorKey( "nodeGadget:color" );
static IECore::InternedString g_shapeKey( "nodeGadget:shape" );
static IECore::InternedString g_focusGadgetVisibleKey( "nodeGadget:focusGadgetVisible" );
static IECore::InternedString g_inputNoduleLabelsVisibleKey( "nodeGadget:inputNoduleLabelsVisible" );
static IECore::InternedString g_outputNoduleLabelsVisibleKey( "nodeGadget:outputNoduleLabelsVisible" );
static IECore::InternedString g_iconKey( "icon" );
static IECore::InternedString g_iconScaleKey( "iconScale" );
static IECore::InternedString g_errorGadgetName( "__error" );
Expand Down Expand Up @@ -700,6 +702,7 @@ StandardNodeGadget::StandardNodeGadget( Gaffer::NodePtr node, bool auxiliary )
dragMoveSignal().connect( boost::bind( &StandardNodeGadget::dragMove, this, ::_1, ::_2 ) );
dragLeaveSignal().connect( boost::bind( &StandardNodeGadget::dragLeave, this, ::_1, ::_2 ) );
dropSignal().connect( boost::bind( &StandardNodeGadget::drop, this, ::_1, ::_2 ) );
noduleAddedSignal().connect( boost::bind( &StandardNodeGadget::noduleAdded, this, ::_2 ) );

for( int e = FirstEdge; e <= LastEdge; e++ )
{
Expand All @@ -722,6 +725,7 @@ StandardNodeGadget::StandardNodeGadget( Gaffer::NodePtr node, bool auxiliary )
updateIcon();
updateShape();
updateFocusGadgetVisibility();
applyNoduleLabelVisibilityMetadata();
}

StandardNodeGadget::~StandardNodeGadget()
Expand Down Expand Up @@ -1144,10 +1148,7 @@ void StandardNodeGadget::leave( Gadget *gadget )
{
if( m_labelsVisibleOnHover )
{
for( StandardNodule::RecursiveIterator it( gadget ); !it.done(); ++it )
{
(*it)->setLabelVisible( false );
}
applyNoduleLabelVisibilityMetadata();
}
}

Expand Down Expand Up @@ -1202,10 +1203,7 @@ bool StandardNodeGadget::dragLeave( GadgetPtr gadget, const DragDropEvent &event
if( m_dragDestination != event.destinationGadget )
{
m_dragDestination->setHighlighted( false );
for( StandardNodule::RecursiveIterator it( this ); !it.done(); ++it )
{
(*it)->setLabelVisible( false );
}
applyNoduleLabelVisibilityMetadata();
}
m_dragDestination = nullptr;

Expand All @@ -1222,14 +1220,25 @@ bool StandardNodeGadget::drop( GadgetPtr gadget, const DragDropEvent &event )
connect( event, m_dragDestination );

m_dragDestination->setHighlighted( false );
for( StandardNodule::RecursiveIterator it( this ); !it.done(); ++it )
{
(*it)->setLabelVisible( false );
}
applyNoduleLabelVisibilityMetadata();

m_dragDestination = nullptr;
return true;
}

void StandardNodeGadget::noduleAdded( Nodule *nodule )
{
if( auto standardNodule = IECore::runTimeCast<StandardNodule>( nodule ) )
{
IECore::ConstBoolDataPtr d = standardNodule->plug()->direction() == Plug::Direction::In ?
Gaffer::Metadata::value<IECore::BoolData>( node(), g_inputNoduleLabelsVisibleKey ) :
Gaffer::Metadata::value<IECore::BoolData>( node(), g_outputNoduleLabelsVisibleKey )
;

standardNodule->setLabelVisible( d ? d->readable() : false );
}
}

ConnectionCreator *StandardNodeGadget::closestDragDestination( const DragDropEvent &event ) const
{
if( event.buttons != DragDropEvent::Left )
Expand Down Expand Up @@ -1303,6 +1312,10 @@ void StandardNodeGadget::nodeMetadataChanged( IECore::InternedString key )
{
updateFocusGadgetVisibility();
}
else if( key == g_inputNoduleLabelsVisibleKey || key == g_outputNoduleLabelsVisibleKey )
{
applyNoduleLabelVisibilityMetadata();
}
}

bool StandardNodeGadget::updateUserColor()
Expand Down Expand Up @@ -1464,6 +1477,28 @@ void StandardNodeGadget::updateFocusGadgetVisibility()
m_focusGadget->setVisible( !d || d->readable() );
}

void StandardNodeGadget::applyNoduleLabelVisibilityMetadata()
{
bool inputVisible = false;
if( IECore::ConstBoolDataPtr d = Gaffer::Metadata::value<IECore::BoolData>( node(), g_inputNoduleLabelsVisibleKey ) )
{
inputVisible = d->readable();
}

bool outputVisible = false;
if( IECore::ConstBoolDataPtr d = Gaffer::Metadata::value<IECore::BoolData>( node(), g_outputNoduleLabelsVisibleKey ) )
{
outputVisible = d->readable();
}

for( StandardNodule::RecursiveIterator it( this ); !it.done(); ++it )
{
(*it)->setLabelVisible(
(*it)->plug()->direction() == Plug::Direction::In ? inputVisible : outputVisible
);
}
}

StandardNodeGadget::ErrorGadget *StandardNodeGadget::errorGadget( bool createIfMissing )
{
if( ErrorGadget *result = getChild<ErrorGadget>( g_errorGadgetName ) )
Expand Down
58 changes: 53 additions & 5 deletions src/GafferUI/StandardNodule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ bool StandardNodule::dragEnter( GadgetPtr gadget, const DragDropEvent &event )
Nodule *prevDestination = IECore::runTimeCast<Nodule>( event.destinationGadget.get() );
if( !prevDestination || prevDestination->plug()->node() != plug()->node() )
{
setCompatibleLabelsVisible( event, true );
setCompatibleLabelsVisible( event );
}

dirty( DirtyType::Render );
Expand Down Expand Up @@ -397,19 +397,40 @@ bool StandardNodule::dragLeave( GadgetPtr gadget, const DragDropEvent &event )
{
if( newDestination->plug()->node() != plug()->node() )
{
setCompatibleLabelsVisible( event, false );
if( auto nodeGadget = ancestor<StandardNodeGadget>() )
{
nodeGadget->applyNoduleLabelVisibilityMetadata();
}
else
{
setCompatibleLabelsVisible( event, false );
}
}
}
else if( NodeGadget *newDestination = IECore::runTimeCast<NodeGadget>( event.destinationGadget.get() ) )
{
if( newDestination->node() != plug()->node() )
{
setCompatibleLabelsVisible( event, false );
if( auto nodeGadget = ancestor<StandardNodeGadget>() )
{
nodeGadget->applyNoduleLabelVisibilityMetadata();
}
else
{
setCompatibleLabelsVisible( event, false );
}
}
}
else
{
setCompatibleLabelsVisible( event, false );
if( auto nodeGadget = ancestor<StandardNodeGadget>() )
{
nodeGadget->applyNoduleLabelVisibilityMetadata();
}
else
{
setCompatibleLabelsVisible( event, false );
}
}
dirty( DirtyType::Render );
}
Expand All @@ -434,7 +455,14 @@ bool StandardNodule::dragEnd( GadgetPtr gadget, const DragDropEvent &event )
bool StandardNodule::drop( GadgetPtr gadget, const DragDropEvent &event )
{
setHighlighted( false );
setCompatibleLabelsVisible( event, false );
if( auto nodeGadget = ancestor<StandardNodeGadget>() )
{
nodeGadget->applyNoduleLabelVisibilityMetadata();
}
else
{
setCompatibleLabelsVisible( event, false );
}

if( ConnectionCreator *creator = IECore::runTimeCast<ConnectionCreator>( event.sourceGadget.get() ) )
{
Expand Down Expand Up @@ -474,6 +502,26 @@ void StandardNodule::setCompatibleLabelsVisible( const DragDropEvent &event, boo
}
}

void StandardNodule::setCompatibleLabelsVisible( const DragDropEvent &event )
{
NodeGadget *nodeGadget = ancestor<NodeGadget>();
if( !nodeGadget )
{
return;
}

ConnectionCreator *creator = IECore::runTimeCast<ConnectionCreator>( event.sourceGadget.get() );
if( !creator )
{
return;
}

for( StandardNodule::RecursiveIterator it( nodeGadget ); !it.done(); ++it )
{
(*it)->setLabelVisible( creator->canCreateConnection( it->get()->plug() ) ? true : false );
}
}

void StandardNodule::plugMetadataChanged( const Gaffer::Plug *plug, IECore::InternedString key )
{
if( plug != this->plug() )
Expand Down

0 comments on commit 6ca6fd7

Please sign in to comment.