From 1620f5e1b188d5e6f4729c8ba006c0f5e368980c Mon Sep 17 00:00:00 2001 From: Eric Mehl Date: Tue, 10 Dec 2024 14:57:24 -0500 Subject: [PATCH 1/7] VisualiserTool : Add primitive variable menu --- Changes.md | 2 +- python/GafferSceneUI/VisualiserToolUI.py | 65 ++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/Changes.md b/Changes.md index a95f86714c..c1b56e1fdb 100644 --- a/Changes.md +++ b/Changes.md @@ -11,7 +11,7 @@ Features - Inference : Loads ONNX models and performance inference using an array of input tensors. - ImageToTensor : Converts images to tensors for use with the Inference node. - TensorToImage : Converts tensors back to images following inference. -- VisualiserTool : Added tool to 3D viewer for visualising primitive variables on meshes. +- VisualiserTool : Added tool to 3D viewer for visualising primitive variables on meshes. A list of available variable names for the current selection is available from the `dataName` context menu. Improvements ------------ diff --git a/python/GafferSceneUI/VisualiserToolUI.py b/python/GafferSceneUI/VisualiserToolUI.py index 4546bb000f..bb70e71e86 100644 --- a/python/GafferSceneUI/VisualiserToolUI.py +++ b/python/GafferSceneUI/VisualiserToolUI.py @@ -34,6 +34,11 @@ # ########################################################################## +import functools + +import IECore +import IECoreScene + import Gaffer import GafferUI import GafferSceneUI @@ -118,3 +123,63 @@ }, ) + +def __setDataName( plug, name, checked ) : + + plug.setValue( name ) + +def __primitiveVariableContextMenu( menuDefinition, plugValueWidget ) : + + plug = plugValueWidget.getPlug() + node = plug.node() + if not isinstance( node, GafferSceneUI.VisualiserTool ) : + return + if plug != node["dataName"] : + return + + scenePlug = node.view()["in"].getInput() + scriptNode = scenePlug.ancestor( Gaffer.ScriptNode ) + selection = GafferSceneUI.ScriptNodeAlgo.getSelectedPaths( scriptNode ) + + primVars = [] + + for path in selection.paths() : + primitive = scenePlug.object( path ) + if not isinstance( primitive, IECoreScene.MeshPrimitive ) : + continue + + for v in primitive.keys() : + if primitive[v].interpolation not in [ + IECoreScene.PrimitiveVariable.Interpolation.FaceVarying, + IECoreScene.PrimitiveVariable.Interpolation.Uniform, + IECoreScene.PrimitiveVariable.Interpolation.Vertex, + ] : + continue + + if not isinstance( + primitive[v].data, + ( + IECore.IntVectorData, + IECore.FloatVectorData, + IECore.V2fVectorData, + IECore.Color3fVectorData, + IECore.V3fVectorData, + ) + ) : + continue + + primVars.append( v ) + + if len( primVars ) > 0 : + menuDefinition.prepend( "/PrimitiveVariablesDivider", { "divider" : True } ) + + for v in reversed( sorted( primVars ) ) : + menuDefinition.prepend( + f"/Primitive Variables/{v}", + { + "command" : functools.partial( __setDataName, plug, v ), + "checkBox" : plug.getValue() == v, + } + ) + +GafferUI.PlugValueWidget.popupMenuSignal().connect( __primitiveVariableContextMenu ) From f761e90ea5e0fba84e95409a6388f28476c0e261 Mon Sep 17 00:00:00 2001 From: Eric Mehl Date: Thu, 12 Dec 2024 15:13:00 -0500 Subject: [PATCH 2/7] fixup! VisualiserTool : Add primitive variable menu --- python/GafferSceneUI/VisualiserToolUI.py | 53 ++++++++++++------------ 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/python/GafferSceneUI/VisualiserToolUI.py b/python/GafferSceneUI/VisualiserToolUI.py index bb70e71e86..e5bcc5aca9 100644 --- a/python/GafferSceneUI/VisualiserToolUI.py +++ b/python/GafferSceneUI/VisualiserToolUI.py @@ -139,36 +139,37 @@ def __primitiveVariableContextMenu( menuDefinition, plugValueWidget ) : scenePlug = node.view()["in"].getInput() scriptNode = scenePlug.ancestor( Gaffer.ScriptNode ) - selection = GafferSceneUI.ScriptNodeAlgo.getSelectedPaths( scriptNode ) + with node.view().context() : + selection = GafferSceneUI.ScriptNodeAlgo.getSelectedPaths( scriptNode ) - primVars = [] + primVars = [] - for path in selection.paths() : - primitive = scenePlug.object( path ) - if not isinstance( primitive, IECoreScene.MeshPrimitive ) : - continue - - for v in primitive.keys() : - if primitive[v].interpolation not in [ - IECoreScene.PrimitiveVariable.Interpolation.FaceVarying, - IECoreScene.PrimitiveVariable.Interpolation.Uniform, - IECoreScene.PrimitiveVariable.Interpolation.Vertex, - ] : - continue - - if not isinstance( - primitive[v].data, - ( - IECore.IntVectorData, - IECore.FloatVectorData, - IECore.V2fVectorData, - IECore.Color3fVectorData, - IECore.V3fVectorData, - ) - ) : + for path in selection.paths() : + primitive = scenePlug.object( path ) + if not isinstance( primitive, IECoreScene.MeshPrimitive ) : continue - primVars.append( v ) + for v in primitive.keys() : + if primitive[v].interpolation not in [ + IECoreScene.PrimitiveVariable.Interpolation.FaceVarying, + IECoreScene.PrimitiveVariable.Interpolation.Uniform, + IECoreScene.PrimitiveVariable.Interpolation.Vertex, + ] : + continue + + if not isinstance( + primitive[v].data, + ( + IECore.IntVectorData, + IECore.FloatVectorData, + IECore.V2fVectorData, + IECore.Color3fVectorData, + IECore.V3fVectorData, + ) + ) : + continue + + primVars.append( v ) if len( primVars ) > 0 : menuDefinition.prepend( "/PrimitiveVariablesDivider", { "divider" : True } ) From 9391d5b5cc5d7d302dcd1e3b7fdddfe96784aeea Mon Sep 17 00:00:00 2001 From: Eric Mehl Date: Thu, 12 Dec 2024 15:14:50 -0500 Subject: [PATCH 3/7] fixup! VisualiserTool : Add primitive variable menu --- python/GafferSceneUI/VisualiserToolUI.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/GafferSceneUI/VisualiserToolUI.py b/python/GafferSceneUI/VisualiserToolUI.py index e5bcc5aca9..4c1099fd75 100644 --- a/python/GafferSceneUI/VisualiserToolUI.py +++ b/python/GafferSceneUI/VisualiserToolUI.py @@ -138,7 +138,7 @@ def __primitiveVariableContextMenu( menuDefinition, plugValueWidget ) : return scenePlug = node.view()["in"].getInput() - scriptNode = scenePlug.ancestor( Gaffer.ScriptNode ) + scriptNode = node.view().scriptNode() with node.view().context() : selection = GafferSceneUI.ScriptNodeAlgo.getSelectedPaths( scriptNode ) From 81b2641dba0ed49b9286a54af15778414084f391 Mon Sep 17 00:00:00 2001 From: Eric Mehl Date: Thu, 12 Dec 2024 15:20:33 -0500 Subject: [PATCH 4/7] fixup! VisualiserTool : Add primitive variable menu --- python/GafferSceneUI/VisualiserToolUI.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/GafferSceneUI/VisualiserToolUI.py b/python/GafferSceneUI/VisualiserToolUI.py index 4c1099fd75..c6f391e0bc 100644 --- a/python/GafferSceneUI/VisualiserToolUI.py +++ b/python/GafferSceneUI/VisualiserToolUI.py @@ -64,7 +64,7 @@ "description", """ Specifies the name of the primitive variable to visualise. The data should - be of type float, V2f or V3f. + be of type int, float, V2f, Color3f or V3f. """, "toolbarLayout:section", "Bottom", From 87903f18aa3998c01757d3b77dee9ec776c47d58 Mon Sep 17 00:00:00 2001 From: Eric Mehl Date: Thu, 12 Dec 2024 15:24:27 -0500 Subject: [PATCH 5/7] fixup! VisualiserTool : Add primitive variable menu --- python/GafferSceneUI/VisualiserToolUI.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python/GafferSceneUI/VisualiserToolUI.py b/python/GafferSceneUI/VisualiserToolUI.py index c6f391e0bc..bf61a02e27 100644 --- a/python/GafferSceneUI/VisualiserToolUI.py +++ b/python/GafferSceneUI/VisualiserToolUI.py @@ -145,6 +145,9 @@ def __primitiveVariableContextMenu( menuDefinition, plugValueWidget ) : primVars = [] for path in selection.paths() : + if not scenePlug.exists( path ) : + continue + primitive = scenePlug.object( path ) if not isinstance( primitive, IECoreScene.MeshPrimitive ) : continue From c8b30c75166160c95f6f34e5522f5b643c0d2a4f Mon Sep 17 00:00:00 2001 From: Eric Mehl Date: Thu, 12 Dec 2024 15:34:03 -0500 Subject: [PATCH 6/7] fixup! VisualiserTool : Add primitive variable menu --- python/GafferSceneUI/VisualiserToolUI.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/GafferSceneUI/VisualiserToolUI.py b/python/GafferSceneUI/VisualiserToolUI.py index bf61a02e27..cadf2bde9f 100644 --- a/python/GafferSceneUI/VisualiserToolUI.py +++ b/python/GafferSceneUI/VisualiserToolUI.py @@ -142,7 +142,7 @@ def __primitiveVariableContextMenu( menuDefinition, plugValueWidget ) : with node.view().context() : selection = GafferSceneUI.ScriptNodeAlgo.getSelectedPaths( scriptNode ) - primVars = [] + primVars = set() for path in selection.paths() : if not scenePlug.exists( path ) : @@ -172,7 +172,7 @@ def __primitiveVariableContextMenu( menuDefinition, plugValueWidget ) : ) : continue - primVars.append( v ) + primVars.add( v ) if len( primVars ) > 0 : menuDefinition.prepend( "/PrimitiveVariablesDivider", { "divider" : True } ) From 3d656e10b45d02b43cd933a83a9760b6332de8d5 Mon Sep 17 00:00:00 2001 From: Eric Mehl Date: Fri, 13 Dec 2024 10:48:56 -0500 Subject: [PATCH 7/7] fixup! VisualiserTool : Add primitive variable menu --- python/GafferSceneUI/VisualiserToolUI.py | 124 +++++++++++++---------- 1 file changed, 71 insertions(+), 53 deletions(-) diff --git a/python/GafferSceneUI/VisualiserToolUI.py b/python/GafferSceneUI/VisualiserToolUI.py index cadf2bde9f..072c745517 100644 --- a/python/GafferSceneUI/VisualiserToolUI.py +++ b/python/GafferSceneUI/VisualiserToolUI.py @@ -63,13 +63,15 @@ "description", """ - Specifies the name of the primitive variable to visualise. The data should - be of type int, float, V2f, Color3f or V3f. + Specifies the name of the primitive variable to visualise. Variables of + type int, float, V2f, Color3f or V3f can be visualised. """, "toolbarLayout:section", "Bottom", "toolbarLayout:width", 150, + "plugValueWidget:type", "GafferSceneUI.VisualiserToolUI._DataNameChooser", + ], "opacity" : [ @@ -124,66 +126,82 @@ }, ) -def __setDataName( plug, name, checked ) : +class _DataNameChooser( GafferUI.PlugValueWidget ) : - plug.setValue( name ) + def __init__( self, plug, **kw ) : -def __primitiveVariableContextMenu( menuDefinition, plugValueWidget ) : + self.__menuButton = GafferUI.MenuButton( + text = plug.getValue(), + menu = GafferUI.Menu( Gaffer.WeakMethod( self.__menuDefinition ) ) + ) - plug = plugValueWidget.getPlug() - node = plug.node() - if not isinstance( node, GafferSceneUI.VisualiserTool ) : - return - if plug != node["dataName"] : - return + GafferUI.PlugValueWidget.__init__( self, self.__menuButton, plug, **kw ) - scenePlug = node.view()["in"].getInput() - scriptNode = node.view().scriptNode() - with node.view().context() : - selection = GafferSceneUI.ScriptNodeAlgo.getSelectedPaths( scriptNode ) + def __menuDefinition( self ) : - primVars = set() + menuDefinition = IECore.MenuDefinition() - for path in selection.paths() : - if not scenePlug.exists( path ) : - continue + node = self.getPlug().node() + if not isinstance( node, GafferSceneUI.VisualiserTool ) : + return + if self.getPlug() != node["dataName"] : + return - primitive = scenePlug.object( path ) - if not isinstance( primitive, IECoreScene.MeshPrimitive ) : - continue + scenePlug = node.view()["in"].getInput() + scriptNode = node.view().scriptNode() + with node.view().context() : + selection = GafferSceneUI.ScriptNodeAlgo.getSelectedPaths( scriptNode ) - for v in primitive.keys() : - if primitive[v].interpolation not in [ - IECoreScene.PrimitiveVariable.Interpolation.FaceVarying, - IECoreScene.PrimitiveVariable.Interpolation.Uniform, - IECoreScene.PrimitiveVariable.Interpolation.Vertex, - ] : - continue + primVars = set() - if not isinstance( - primitive[v].data, - ( - IECore.IntVectorData, - IECore.FloatVectorData, - IECore.V2fVectorData, - IECore.Color3fVectorData, - IECore.V3fVectorData, - ) - ) : + for path in selection.paths() : + if not scenePlug.exists( path ) : continue - primVars.add( v ) - - if len( primVars ) > 0 : - menuDefinition.prepend( "/PrimitiveVariablesDivider", { "divider" : True } ) - - for v in reversed( sorted( primVars ) ) : - menuDefinition.prepend( - f"/Primitive Variables/{v}", - { - "command" : functools.partial( __setDataName, plug, v ), - "checkBox" : plug.getValue() == v, - } - ) + primitive = scenePlug.object( path ) + if not isinstance( primitive, IECoreScene.MeshPrimitive ) : + continue -GafferUI.PlugValueWidget.popupMenuSignal().connect( __primitiveVariableContextMenu ) + for v in primitive.keys() : + if primitive[v].interpolation not in [ + IECoreScene.PrimitiveVariable.Interpolation.FaceVarying, + IECoreScene.PrimitiveVariable.Interpolation.Uniform, + IECoreScene.PrimitiveVariable.Interpolation.Vertex, + ] : + continue + + if not isinstance( + primitive[v].data, + ( + IECore.IntVectorData, + IECore.FloatVectorData, + IECore.V2fVectorData, + IECore.Color3fVectorData, + IECore.V3fVectorData, + ) + ) : + continue + + primVars.add( v ) + + if len( primVars ) == 0 : + menuDefinition.append( "/None Available", { "active" : False } ) + + else : + for v in reversed( sorted( primVars ) ) : + menuDefinition.prepend( + "/" + v, + { + "command" : functools.partial( Gaffer.WeakMethod( self.__setDataName ), v ), + "checkBox" : self.getPlug().getValue() == v, + } + ) + + menuDefinition.prepend( "/PrimVarDivider", { "divider" : True, "label" : "Primitive Variables" } ) + + return menuDefinition + + def __setDataName( self, value, *unused ) : + + self.getPlug().setValue( value ) + self.__menuButton.setText( value )