Skip to content

Commit

Permalink
Merge branch '1.4_maintenance'
Browse files Browse the repository at this point in the history
  • Loading branch information
johnhaddon committed Apr 29, 2024
2 parents 35190d2 + 33839a4 commit bfdea96
Show file tree
Hide file tree
Showing 23 changed files with 390 additions and 19 deletions.
16 changes: 16 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
1.4.x.x (relative to 1.4.1.0)
=======

Features
--------

- LightPositionTool : Added `Diffuse` mode for placing lights along the normal of the target position.

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

Expand All @@ -14,6 +19,10 @@ Improvements
- Changed default value for `principled_bsdf.specular_ior_level` to `0.5`, matching Blender.
- Added support for `uv.tangent` and `uv.tangent_sign` primitive variables to assist in rendering with normal maps (#5269).
- AttributeQuery, PrimitiveVariableQuery, ContextQuery, OptionQuery, ShaderQuery : Added support for querying arrays of length 1 as their equivalent scalar types.
- CodeWidget : Added <kbd>Ctrl</kbd>+<kbd>L</kbd> shortcut for selecting all text on the current line.
- AttributeTweaks, CameraTweaks, ShaderTweaks, OptionTweaks, PrimitiveVariableTweaks :
- Added support for a `{source}` token which is substituted with the original value when tweaking a string in `Replace` mode.
- Added tooltips documenting the tweak modes.

Fixes
-----
Expand All @@ -26,6 +35,13 @@ API

- PlugAlgo : `setValueFromData()` and `canSetValueFromData()` now support conversion of arrays of length 1 to their equivalent scalar types.
- BoxPlug : Added Python bindings for `ValueType`, `PointType` and `ChildType` type aliases.
- RenderPassEditor : Added `deregisterColumn()` method.
- DocumentationAlgo : Added table and strikethrough support to `markdownToHTML()`.

Build
-----

- MacOS : Fixed issue where `Python.framework` may not be found when building with a prebuilt dependencies package.

1.4.1.0 (relative to 1.4.0.0)
=======
Expand Down
5 changes: 4 additions & 1 deletion SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -751,11 +751,14 @@ commandEnv["ENV"]["PATH"] = commandEnv.subst( "$BUILD_DIR/bin" + os.path.pathsep
if env["PLATFORM"] == "win32" :
commandEnv["ENV"]["PATH"] = commandEnv.subst( "$BUILD_DIR/lib" + os.path.pathsep ) + commandEnv["ENV"]["PATH"]

if commandEnv["PLATFORM"]=="darwin" :
if commandEnv["PLATFORM"] == "darwin" :
commandEnv["ENV"]["DYLD_LIBRARY_PATH"] = commandEnv.subst( ":".join(
[ "/System/Library/Frameworks/ImageIO.framework/Resources", "$BUILD_DIR/lib" ] +
split( commandEnv["LOCATE_DEPENDENCY_LIBPATH"] )
) )
commandEnv["ENV"]["DYLD_FRAMEWORK_PATH"] = commandEnv.subst( ":".join(
[ "$BUILD_DIR/lib" ] + split( commandEnv["LOCATE_DEPENDENCY_LIBPATH"] )
) )
elif commandEnv["PLATFORM"] == "win32" :
commandEnv["ENV"]["PATH"] = commandEnv.subst( ";".join( [ "$BUILD_DIR/lib" ] + split( commandEnv[ "LOCATE_DEPENDENCY_LIBPATH" ] ) + [ commandEnv["ENV"]["PATH"] ] ) )
else:
Expand Down
1 change: 1 addition & 0 deletions doc/source/Interface/ControlsAndShortcuts/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ Drop scene location path(s) into Python Editor | {{leftClick}} and drag select
Indent selection | {kbd}`Ctrl` + {kbd}`]`
Unindent selection | {kbd}`Ctrl` + {kbd}`[`
Comment/uncomment selection | {kbd}`Ctrl` + {kbd}`/`
Select current line | {kbd}`Ctrl` + {kbd}`L`


### Execution ###
Expand Down
2 changes: 2 additions & 0 deletions include/Gaffer/TweakPlug.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ class GAFFER_API TweakPlug : public Gaffer::ValuePlug
const std::string &tweakName
) const;

void applyReplaceTweak( const IECore::Data *sourceData, IECore::Data *tweakData ) const;

static const char *modeToString( Gaffer::TweakPlug::Mode mode );

};
Expand Down
4 changes: 4 additions & 0 deletions include/Gaffer/TweakPlug.inl
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ bool TweakPlug::applyTweak(
{
applyListTweak( currentValue, newData.get(), newData.get(), mode, name );
}
else if( mode == TweakPlug::Replace )
{
applyReplaceTweak( currentValue, newData.get() );
}

if( mode != Gaffer::TweakPlug::CreateIfMissing )
{
Expand Down
6 changes: 5 additions & 1 deletion include/GafferSceneUI/LightPositionTool.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,17 @@ class GAFFERSCENEUI_API LightPositionTool : public GafferSceneUI::TransformTool
const float targetDistance
);

// Positions the current selection to be `distance` away from `target`, along `normal`.
void positionAlongNormal( const Imath::V3f &target, const Imath::V3f &normal, const float targetDistance );

enum class Mode
{
Shadow,
Highlight,
Diffuse,

First = Shadow,
Last = Highlight
Last = Diffuse
};

protected :
Expand Down
1 change: 1 addition & 0 deletions python/GafferSceneUI/AttributeTweaksUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@

"tweakPlugValueWidget:allowCreate", True,
"tweakPlugValueWidget:allowRemove", True,
"tweakPlugValueWidget:propertyType", "attribute",

],

Expand Down
1 change: 1 addition & 0 deletions python/GafferSceneUI/CameraTweaksUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@

"tweakPlugValueWidget:allowRemove", True,
"tweakPlugValueWidget:allowCreate", True,
"tweakPlugValueWidget:propertyType", "parameter",

],

Expand Down
5 changes: 4 additions & 1 deletion python/GafferSceneUI/LightPositionToolUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ def __toolTip( tool ) :
result = None
if mode == GafferSceneUI.LightPositionTool.Mode.Shadow :
result = "Hold 'Shift' + 'V' to place shadow pivot\nHold 'V' to place shadow target"
else :
elif mode == GafferSceneUI.LightPositionTool.Mode.Highlight :
result = "Hold 'V' to place highlight target"
else :
result = "Hold 'V' to place diffuse target"

return result

Expand Down Expand Up @@ -89,6 +91,7 @@ def __toolTip( tool ) :

"preset:Shadow", GafferSceneUI.LightPositionTool.Mode.Shadow,
"preset:Highlight", GafferSceneUI.LightPositionTool.Mode.Highlight,
"preset:Diffuse", GafferSceneUI.LightPositionTool.Mode.Diffuse,

"viewer:cyclePresetShortcut", "O",

Expand Down
1 change: 1 addition & 0 deletions python/GafferSceneUI/OptionTweaksUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"tweaks.*" : [

"tweakPlugValueWidget:allowCreate", True,
"tweakPlugValueWidget:propertyType", "option",

],

Expand Down
7 changes: 7 additions & 0 deletions python/GafferSceneUI/RenderPassEditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,13 @@ def registerColumn( cls, groupKey, columnKey, inspectorFunction, section = "Main

section[columnKey] = inspectorFunction

@classmethod
def deregisterColumn( cls, groupKey, columnKey, section = "Main" ) :

sections = cls.__columnRegistry.get( groupKey )
if sections is not None and section in sections.keys() and columnKey in sections[section].keys() :
del sections[section][columnKey]

__addRenderPassButtonMenuSignal = None
## This signal is emitted whenever the add render pass button is clicked.
# If the resulting menu definition has been populated with items,
Expand Down
1 change: 1 addition & 0 deletions python/GafferSceneUI/ShaderTweaksUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
"noduleLayout:visible", False, # Can be shown individually using PlugAdder above
"tweakPlugValueWidget:allowCreate", True,
"tweakPlugValueWidget:allowRemove", True,
"tweakPlugValueWidget:propertyType", "parameter",

],

Expand Down
55 changes: 55 additions & 0 deletions python/GafferSceneUITest/LightPositionToolTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,61 @@ def testPositionHighlight( self ) :
places = 3
)

def __diffuseSource( self, lightP, diffuseP, normal ) :
d = ( lightP - diffuseP ).length()
return diffuseP + normal * d

def testPositionDiffuse( self ) :

random.seed( 42 )

script = Gaffer.ScriptNode()
script["light"] = GafferSceneTest.TestLight()

view = GafferSceneUI.SceneView()
view["in"].setInput( script["light"]["out"] )
GafferSceneUI.ContextAlgo.setSelectedPaths( view.getContext(), IECore.PathMatcher( [ "/light"] ) )

tool = GafferSceneUI.LightPositionTool( view )
tool["active"].setValue( True )

for i in range( 0, 5 ) :
lightP = imath.V3f( random.random() * 10 - 5, random.random() * 10 - 5, random.random() * 10 - 5 )
diffuseP = imath.V3f( random.random() * 10 - 5, random.random() * 10 - 5, random.random() * 10 - 5 )
normal = imath.V3f( random.random() * 2 - 1, random.random() * 2 - 1, random.random() * 2 - 1 ).normalized()

script["light"]["transform"]["translate"].setValue( lightP )

d0 = ( lightP - diffuseP ).length()
upDir = script["light"]["transform"].matrix().multDirMatrix( imath.V3f( 0, 1, 0 ) )

with Gaffer.Context() :
tool.positionAlongNormal( diffuseP, normal, d0 )

p = script["light"]["transform"]["translate"].getValue()

d1 = ( p - diffuseP ).length()
self.assertAlmostEqual( d0, d1, places = 4 )

desiredP = self.__diffuseSource( lightP, diffuseP, normal )

for j in range( 0, 3 ) :
self.assertAlmostEqual( p[j], desiredP[j], places = 4 )

desiredO = imath.M44f()
imath.M44f.rotationMatrixWithUpDir( desiredO, imath.V3f( 0, 0, -1 ), diffuseP - p, upDir )
rotationO = imath.V3f()
desiredO.extractEulerXYZ( rotationO )

o = script["light"]["transform"]["rotate"].getValue()

with self.subTest( f"Iteration {i}" ) :
self.assertAnglesAlmostEqual(
o,
IECore.radiansToDegrees( imath.V3f( rotationO ) ),
places = 3
)

def testEmptySelectionModeChange( self ) :

script = Gaffer.ScriptNode()
Expand Down
30 changes: 30 additions & 0 deletions python/GafferTest/TweakPlugTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,5 +451,35 @@ def testStringListOperations( self ) :
self.assertTrue( plug.applyTweak( data ) )
self.assertEqual( data["v"], IECore.StringData( result ) )

def testStringSubstitutions( self ) :

for source, tweakMode, tweakValue, result in [
# Create modes don't support substitutions.
( None, Gaffer.TweakPlug.Mode.Create, "{source}", "{source}" ),
( None, Gaffer.TweakPlug.Mode.CreateIfMissing, "{source}", "{source}" ),
( IECore.StringData( "a" ), Gaffer.TweakPlug.Mode.Create, "{source}", "{source}" ),
( IECore.StringData( "a" ), Gaffer.TweakPlug.Mode.CreateIfMissing, "{source}", "a" ),
# Neither do list modes.
( IECore.StringData( "a" ), Gaffer.TweakPlug.Mode.ListAppend, "{source}", "a {source}" ),
( IECore.StringData( "a" ), Gaffer.TweakPlug.Mode.ListPrepend, "{source}", "{source} a" ),
# Replace mode does support substitutions.
( IECore.StringData( "a" ), Gaffer.TweakPlug.Mode.Replace, "{source}", "a" ),
( IECore.StringData( "a" ), Gaffer.TweakPlug.Mode.Replace, "prefix{source}", "prefixa" ),
( IECore.StringData( "a" ), Gaffer.TweakPlug.Mode.Replace, "{source}suffix", "asuffix" ),
( IECore.StringData( "a" ), Gaffer.TweakPlug.Mode.Replace, "{source} {source}", "a a" ),
# And works with InternedStringData too.
( IECore.InternedStringData( "a" ), Gaffer.TweakPlug.Mode.Replace, "{source}", "a" ),
( IECore.InternedStringData( "a" ), Gaffer.TweakPlug.Mode.Replace, "prefix{source}", "prefixa" ),
( IECore.InternedStringData( "a" ), Gaffer.TweakPlug.Mode.Replace, "{source}suffix", "asuffix" ),
( IECore.InternedStringData( "a" ), Gaffer.TweakPlug.Mode.Replace, "{source} {source}", "a a" ),
] :
with self.subTest( source = source, tweakMode = tweakMode, tweakValue = tweakValue ) :
plug = Gaffer.TweakPlug( "v", tweakValue, tweakMode )
data = IECore.CompoundData( { "v" : source } )
self.assertTrue( plug.applyTweak( data ) )
if source is not None :
self.assertIs( type( data["v"] ), type( source ) )
self.assertEqual( data["v"].value, result )

if __name__ == "__main__":
unittest.main()
29 changes: 29 additions & 0 deletions python/GafferUI/CodeWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ def __keyPress( self, widget, event ) :
return self.__commentPress()
elif event.key == "Return" and event.modifiers == event.Modifiers.None_ :
return self.__returnPress()
elif event.modifiers == event.Modifiers.Control and event.key == "L" :
return self.__extendSelectionPress()

return False

Expand Down Expand Up @@ -241,6 +243,33 @@ def __returnPress( self ) :

return True

def __extendSelectionPress( self ) :

cursor = self._qtWidget().textCursor()

if cursor.hasSelection() :
# Extend an existing selection to contain the beginning of the
# first selected line through to the end of the last selected line.
selectionEnd = cursor.selectionEnd()
cursor.setPosition( cursor.selectionStart(), cursor.MoveAnchor )
cursor.movePosition( cursor.StartOfLine, cursor.MoveAnchor )
cursor.setPosition( selectionEnd, cursor.KeepAnchor )
cursor.movePosition( cursor.EndOfLine, cursor.KeepAnchor )
else :
# Select the entire line where the cursor is currently positioned.
cursor.movePosition( cursor.StartOfLine, cursor.MoveAnchor )
cursor.movePosition( cursor.EndOfLine, cursor.KeepAnchor )

if not cursor.atEnd() :
# Move the cursor to the start of the next line to allow
# repeated presses to extend the selection to subsequent lines.
cursor.movePosition( cursor.Down, cursor.KeepAnchor )
cursor.movePosition( cursor.StartOfLine, cursor.KeepAnchor )

self._qtWidget().setTextCursor( cursor )

return True

def __textChanged( self, widget ) :

if self.__completionMenu is not None :
Expand Down
1 change: 1 addition & 0 deletions python/GafferUI/ContextVariableTweaksUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"tweaks.*" : [

"tweakPlugValueWidget:allowCreate", True,
"tweakPlugValueWidget:propertyType", "context variable",

]

Expand Down
Loading

0 comments on commit bfdea96

Please sign in to comment.