Skip to content

Commit

Permalink
Merge branch '1.4_maintenance'
Browse files Browse the repository at this point in the history
  • Loading branch information
murraystevenson committed Jun 24, 2024
2 parents dd6f30d + 52a98f6 commit aee5c21
Show file tree
Hide file tree
Showing 32 changed files with 1,927 additions and 193 deletions.
12 changes: 8 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ jobs:
# test user rather than as root.
testRunner: su testUser -c
sconsCacheMegabytes: 400
jobs: 4

- name: linux-debug-gcc9
os: ubuntu-20.04
Expand All @@ -58,6 +59,7 @@ jobs:
# Debug builds are ludicrously big, so we must use a larger cache
# limit. In practice this compresses down to 4-500Mb.
sconsCacheMegabytes: 2500
jobs: 4

- name: linux-gcc11
os: ubuntu-20.04
Expand All @@ -70,6 +72,7 @@ jobs:
# test user rather than as root.
testRunner: su testUser -c
sconsCacheMegabytes: 400
jobs: 4

- name: windows
os: windows-2019
Expand All @@ -78,7 +81,8 @@ jobs:
containerImage:
testRunner: Invoke-Expression
testArguments: -excludedCategories performance GafferTest GafferVDBTest GafferUSDTest GafferSceneTest GafferDispatchTest GafferOSLTest GafferImageTest GafferUITest GafferImageUITest GafferSceneUITest GafferDispatchUITest GafferOSLUITest GafferUSDUITest GafferVDBUITest GafferDelightUITest GafferTractorTest GafferTractorUITest
sconsCacheMegabytes: 400
sconsCacheMegabytes: 800
jobs: 4

runs-on: ${{ matrix.os }}

Expand Down Expand Up @@ -170,7 +174,7 @@ jobs:
- name: Build Gaffer
run: |
scons -j 2 build BUILD_TYPE=${{ matrix.buildType }} OPTIONS=.github/workflows/main/sconsOptions
scons -j ${{ matrix.jobs }} build BUILD_TYPE=${{ matrix.buildType }} OPTIONS=.github/workflows/main/sconsOptions
env:
PYTHONUTF8: 1

Expand Down Expand Up @@ -203,7 +207,7 @@ jobs:
]
)
#Build Arnold extension
subprocess.check_call( "scons -j 2 build BUILD_TYPE=${{ matrix.buildType }} OPTIONS=.github/workflows/main/sconsOptions", shell = True )
subprocess.check_call( "scons -j ${{ matrix.jobs }} build BUILD_TYPE=${{ matrix.buildType }} OPTIONS=.github/workflows/main/sconsOptions", shell = True )
if os.name != "nt" :
# Test Arnold extension
Expand Down Expand Up @@ -235,7 +239,7 @@ jobs:
run: |
# Treats warnings-as-errors so we know about broken links
echo "::add-matcher::./.github/workflows/main/problemMatchers/sphinx.json"
scons -j 2 package BUILD_TYPE=${{ matrix.buildType }} OPTIONS=.github/workflows/main/sconsOptions
scons -j ${{ matrix.jobs }} package BUILD_TYPE=${{ matrix.buildType }} OPTIONS=.github/workflows/main/sconsOptions
echo "::remove-matcher owner=sphinx::"
env:
PYTHONUTF8: 1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/main/installDependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@

# Determine default archive URL.

defaultURL = "https://github.com/ImageEngine/cortex/releases/download/10.5.8.0/cortex-10.5.8.0-{platform}{buildEnvironment}.{extension}"
defaultURL = "https://github.com/ImageEngine/cortex/releases/download/10.5.9.0/cortex-10.5.9.0-{platform}{buildEnvironment}.{extension}"

# Parse command line arguments.

Expand Down
50 changes: 48 additions & 2 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,51 @@ Breaking Changes
- Metadata : Path based registrations to a Node or Plug now override equivalent registrations on its descendants.
- TweakPlugValueWidget : Removed support for `tweakPlugValueWidget:allowCreate` and `tweakPlugValueWidget:allowRemove` metadata.

1.4.x.x (relative to 1.4.7.0)
1.4.x.x (relative to 1.4.8.0)
=======



1.4.8.0 (relative to 1.4.7.0)
=======

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

- SceneReader : ModelAPI `extentsHints` are now considered when loading the bounding box for a location in Gaffer. This can significantly reduce the time taken to load bounds for large USD assemblies. If necessary, this behaviour can be disabled by setting the `IECOREUSD_USE_MODELAPI_BOUNDS` environment variable with a value of `0`.
- ColorChooser :
- Added channel names to identify sliders.
- Setting the saturation to zero no longer resets the hue and setting the value to zero no longer resets the hue and saturation.
- RenderPassEditor : Added "Select Affected Objects" popup menu item.
- Annotations :
- Added support for `{plug}` value substitutions in node annotations.
- Added <kbd>Ctrl</kbd> + <kbd>Enter</kbd> keyboard shortcut to annotation dialogue. This applies the annotation and closes the dialogue.
- LightEditor : Added support for Arnold light blockers and barndoor, gobo and decay light filters.

Fixes
-----

- Cycles : Fixed rendering to the Catalogue using the batch Render node (#5905). Note that rendering a mixture of Catalogue and file outputs is still not supported, and in this case any file outputs will be ignored.
- CodeWidget : Fixed bug that could prevent changes from being committed while the completion menu was visible.
- Loop : Fixed handling of empty `indexVariable`. This now disables the Loop instead of creating an unnamed context variable.
- ColorChooser : Fixed emission of `colorChangedSignal()` while the widget was in an inconsistent internal state.
- LazyMethod : Fixed errors caused by running idle callbacks without a valid Qt Widget.

API
---

- LightEditor : Added `deregisterColumn()` method for removing columns.
- ShaderUI : Added support for `nodeGadget:color` metadata registered against `{shaderType}:{shaderName}`, to specify per-shader colouring of nodes in the GraphEditor.
- ArnoldShaderUI : Added support for `gaffer.nodeGadget.color` RGB metadata in `.mtd` files, to specify per-shader colouring of nodes in the GraphEditor.
- Loop : Added `nextIterationContext()` method.
- AnnotationsGadget : Added `annotationText()` method.
- ParallelAlgoTest : Added `UIThreadCallHandler.receive()` method.
- LightEditor : Added `registerShaderParameter()` method for registering parameters for shader attributes that are not the same as the `rendererKey`.

Build
-----

- Cortex : Updated to version 10.5.9.0.

1.4.7.0 (relative to 1.4.6.0)
=======
Expand Down Expand Up @@ -592,11 +630,19 @@ Build
- Removed QtNetworkAuth library.
- USD : Updated to version 23.11.

1.3.16.x (relative to 1.3.16.5)
1.3.16.x (relative to 1.3.16.6)
========



1.3.16.6 (relative to 1.3.16.5)
========

Fixes
-----

- LazyMethod : Fixed errors caused by running idle callbacks without a valid Qt Widget.

1.3.16.5 (relative to 1.3.16.4)
========

Expand Down
4 changes: 4 additions & 0 deletions include/Gaffer/Loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ class GAFFER_API Loop : public ComputeNode
Gaffer::Plug *correspondingInput( const Gaffer::Plug *output ) override;
const Gaffer::Plug *correspondingInput( const Gaffer::Plug *output ) const override;

/// Returns the context that will be used to evaluate `nextPlug()` in
/// the next iteration of the loop (relative to the current context).
ContextPtr nextIterationContext() const;

void affects( const Plug *input, DependencyNode::AffectedPlugsContainer &outputs ) const override;

protected :
Expand Down
75 changes: 68 additions & 7 deletions include/GafferUI/AnnotationsGadget.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#pragma once

#include "Gaffer/MetadataAlgo.h"
#include "Gaffer/ParallelAlgo.h"

#include "GafferUI/Gadget.h"

Expand Down Expand Up @@ -74,6 +75,10 @@ class GAFFERUI_API AnnotationsGadget : public Gadget
void setVisibleAnnotations( const IECore::StringAlgo::MatchPattern &patterns );
const IECore::StringAlgo::MatchPattern &getVisibleAnnotations() const;

/// Returns the text currently being rendered for the specified
/// annotation. Only really intended for use in the unit tests.
const std::string &annotationText( const Gaffer::Node *node, IECore::InternedString annotation = "user" ) const;

bool acceptsParent( const GraphComponent *potentialParent ) const override;

protected :
Expand All @@ -90,29 +95,85 @@ class GAFFERUI_API AnnotationsGadget : public Gadget

private :

GraphGadget *graphGadget();
const GraphGadget *graphGadget() const;

struct Annotations;

// Update process
// ==============
//
// We query annotation metadata and store it ready for rendering in our
// `m_annotations` data structure. This occurs in synchronous, lazy and
// asynchronous phases as performance requirements dictate.
//
// In the first phase, these two methods ensure that `m_annotations`
// always has an entry for each NodeGadget being drawn by the
// GraphGadget. This is done synchronously with the addition and removal
// of children.
void graphGadgetChildAdded( GraphComponent *child );
void graphGadgetChildRemoved( const GraphComponent *child );
// These accessors can then be used to find the annotations (if any)
// for a node.
Annotations *annotations( const Gaffer::Node *node );
const Annotations *annotations( const Gaffer::Node *node ) const;
// We then use `nodeMetadataChanged()` to dirty individual annotations
// when the metadata has changed. We don't query the metadata at this
// point, as it's fairly typical to receive many metadata edits at once
// and we want to batch the updates. We might not even be visible when
// the edits are made.
void nodeMetadataChanged( IECore::TypeId nodeTypeId, IECore::InternedString key, Gaffer::Node *node );
void update() const;
// We lazily call `update()` from `renderLayer()` to query all dirty
// metadata just in time for rendering. Such update are fairly
// infrequent because annotations are edited infrequently.
void update();
// Some annotations use `{}` syntax to substitute in the values of
// plugs. For these we use `plugDirtied()` to check if the substitutions
// are affected and dirty them when necessary. Plugs are dirtied
// frequently and many don't affect the substitutions at all, so this is
// performed at a finer level of granularity than `update()`.
void plugDirtied( const Gaffer::Plug *plug, Annotations *annotations );
// If the substitutions are from computed plugs, then we also need to
// update when the context changes.
void scriptContextChanged();
// Some plug substitutions may depend on computes, in which case we must
// perform the substitutions in a BackgroundTask to avoid blocking the
// UI. This function schedules such a task, or if the values are not
// computes, does the substitutions directly on the UI thread. This is
// done on a per-node basis, so that slow updates for one node do not
// prevent other nodes updating rapidly.
void schedulePlugValueSubstitutions( const Gaffer::Node *node, Annotations *annotations );
// These two functions do the actual work of calculating and applying
// substitutions.
std::unordered_map<IECore::InternedString, std::string> substitutedRenderText( const Gaffer::Node *node, const Annotations &annotations );
void applySubstitutedRenderText( const std::unordered_map<IECore::InternedString, std::string> &renderText, Annotations &annotations );
// When we are hidden, we want to cancel all background tasks.
void visibilityChanged();

struct StandardAnnotation : public Gaffer::MetadataAlgo::Annotation
{
StandardAnnotation( const Gaffer::MetadataAlgo::Annotation &a, IECore::InternedString name ) : Annotation( a ), name( name ) {}
IECore::InternedString name;
std::string renderText;
};

struct Annotations
{
bool dirty = true;
std::vector<Gaffer::MetadataAlgo::Annotation> standardAnnotations;
std::vector<StandardAnnotation> standardAnnotations;
bool bookmarked = false;
IECore::InternedString numericBookmark;
bool renderable = false;
bool hasPlugValueSubstitutions = false;
bool hasContextSensitiveSubstitutions = false;
Gaffer::Signals::ScopedConnection plugDirtiedConnection;
std::unique_ptr<Gaffer::BackgroundTask> substitutionsTask;
};

Gaffer::Signals::ScopedConnection m_graphGadgetChildAddedConnection;
Gaffer::Signals::ScopedConnection m_graphGadgetChildRemovedConnection;
Gaffer::Signals::ScopedConnection m_scriptContextChangedConnection;

using AnnotationsContainer = std::unordered_map<const NodeGadget *, Annotations>;
mutable AnnotationsContainer m_annotations;
mutable bool m_dirty;
AnnotationsContainer m_annotations;
bool m_dirty;

IECore::StringAlgo::MatchPattern m_visibleAnnotations;

Expand Down
50 changes: 42 additions & 8 deletions python/GafferArnoldUI/ArnoldShaderUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@
import GafferSceneUI
import GafferArnold

# Arnold shaders to add to the light editor.
lightEditorShaders = {
# "shaderName" : ( "shaderAttributeName", "lightEditorSection" )
"light_blocker" : ( "ai:lightFilter:filter", "Blocker" ),
"barndoor" : ( "ai:lightFilter:barndoor", "Barndoor" ),
"gobo" : ( "ai:lightFilter:gobo", "Gobo" ),
"light_decay" : ( "ai:lightFilter:light_decay", "Decay" ),
}

##########################################################################
# Utilities to make it easier to work with the Arnold API, which has a
# fairly bare wrapping using ctypes.
Expand Down Expand Up @@ -231,6 +240,15 @@ def __translateNodeMetadata( nodeEntry ) :
if iconScale is not None :
__metadata[nodeName]["iconScale"] = iconScale

# Node color.

color = __aiMetadataGetRGB( nodeEntry, None, "gaffer.nodeGadget.color" )
if color is not None :
Gaffer.Metadata.registerValue( "ai:surface:{}".format( nodeName ), "nodeGadget:color", color )

# Parameters
# ----------

paramIt = arnold.AiNodeEntryGetParamIterator( nodeEntry )
while not arnold.AiParamIteratorFinished( paramIt ) :

Expand Down Expand Up @@ -328,14 +346,6 @@ def __translateNodeMetadata( nodeEntry ) :
parent = paramPath.rsplit( '.', 1 )[0]
__metadata[parent]["layout:section:%s:collapsed" % page] = collapsed

if (
arnold.AiNodeEntryGetType( nodeEntry ) == arnold.AI_NODE_LIGHT and
__aiMetadataGetStr( nodeEntry, paramName, "gaffer.plugType" ) != ""
) :
GafferSceneUI.LightEditor.registerParameter(
"ai:light", paramName, page
)

# Label from OSL "label"
label = __aiMetadataGetStr( nodeEntry, paramName, "label" )
if label is None :
Expand All @@ -347,6 +357,27 @@ def __translateNodeMetadata( nodeEntry ) :
__metadata[paramPath]["label"] = label
__metadata[paramPath]["noduleLayout:label"] = label

if (
arnold.AiNodeEntryGetType( nodeEntry ) == arnold.AI_NODE_LIGHT and
__aiMetadataGetStr( nodeEntry, paramName, "gaffer.plugType" ) != ""
) :
GafferSceneUI.LightEditor.registerParameter(
"ai:light", paramName, page
)

if (
nodeName in lightEditorShaders and
__aiMetadataGetStr( nodeEntry, paramName, "gaffer.plugType" ) != ""
) :
attributeName, sectionName = lightEditorShaders[nodeName]
GafferSceneUI.LightEditor.registerShaderParameter(
"ai:light",
paramName,
attributeName,
sectionName,
f"{page} {label}" if page is not None and label is not None else paramName
)

childComponents = {
arnold.AI_TYPE_VECTOR2 : "xy",
arnold.AI_TYPE_VECTOR : "xyz",
Expand Down Expand Up @@ -447,6 +478,9 @@ def addActivator( activator ) :
GafferSceneUI.LightEditor.registerParameter( "ai:light", "width", "Shape" )
GafferSceneUI.LightEditor.registerParameter( "ai:light", "height", "Shape" )

# Manually add the `filteredLights` parameter for `light_blocker`
GafferSceneUI.LightEditor.registerAttribute( "ai:light", "filteredLights", "Blocker" )

##########################################################################
# Gaffer Metadata queries. These are implemented using the preconstructed
# registry above.
Expand Down
2 changes: 1 addition & 1 deletion python/GafferSceneUI/EditScopeUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def _summary( processor, linkCreator ) :
summaries[0] = summaries[0][0].upper() + summaries[0][1:]
return " and ".join( summaries )

GafferUI.EditScopeUI.ProcessorWidget.registerProcessorWidget( "AttributeEdits TransformEdits *LightEdits *SurfaceEdits", __LocationEditsWidget )
GafferUI.EditScopeUI.ProcessorWidget.registerProcessorWidget( "AttributeEdits TransformEdits *LightEdits *SurfaceEdits *FilterEdits", __LocationEditsWidget )

class __PruningEditsWidget( _SceneProcessorWidget ) :

Expand Down
Loading

0 comments on commit aee5c21

Please sign in to comment.