Skip to content

Commit

Permalink
Merge pull request #5424 from johnhaddon/collect
Browse files Browse the repository at this point in the history
Collect : Add new node for collecting arbitrary values
  • Loading branch information
johnhaddon authored Aug 23, 2023
2 parents d66ac31 + 54be42e commit 32c42d9
Show file tree
Hide file tree
Showing 17 changed files with 1,760 additions and 1 deletion.
3 changes: 3 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Features
--------

- LightTool : Added manipulator for quad lights.
- Collect : Added a utility node for collecting the values of arbitrary inputs across a range of contexts.

Improvements
------------
Expand All @@ -21,11 +22,13 @@ Fixes
- Arnold : Fixed screen window export for Lentil cameras.
- Application : Fixed the `-threads` argument to clamp the number of threads to the number of available hardware cores (#5403).
- CompareFloat, CompareColor, CompareVector : Worked around crashes in OSL's batched shading system (#5430).
- PlugValueWidget : Fixed search for auxiliary plugs of output plugs. In this case, the inputs are now searched instead of the outputs.

API
---

- ThreadMonitor : Added new class for tracking the threads used to perform processes.
- PlugAlgo : Added `findSource()` method.

Documentation
-------------
Expand Down
119 changes: 119 additions & 0 deletions include/Gaffer/Collect.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2022, Cinesite VFX Ltd. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above
// copyright notice, this list of conditions and the following
// disclaimer.
//
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided with
// the distribution.
//
// * Neither the name of John Haddon nor the names of
// any other contributors to this software may be used to endorse or
// promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#pragma once

#include "Gaffer/ComputeNode.h"
#include "Gaffer/Export.h"
#include "Gaffer/StringPlug.h"
#include "Gaffer/TypedObjectPlug.h"
#include "Gaffer/TypeIds.h"

namespace Gaffer
{

class GAFFER_API Collect : public ComputeNode
{

public :

Collect( const std::string &name = defaultName<Collect>() );
~Collect() override;

GAFFER_NODE_DECLARE_TYPE( Gaffer::Collect, CollectTypeId, ComputeNode );

StringPlug *contextVariablePlug();
const StringPlug *contextVariablePlug() const;

StringPlug *indexContextVariablePlug();
const StringPlug *indexContextVariablePlug() const;

StringVectorDataPlug *contextValuesPlug();
const StringVectorDataPlug *contextValuesPlug() const;

BoolPlug *enabledPlug() override;
const BoolPlug *enabledPlug() const override;

ValuePlug *inPlug();
const ValuePlug *inPlug() const;

ValuePlug *outPlug();
const ValuePlug *outPlug() const;

ObjectPlug *enabledValuesPlug();
const ObjectPlug *enabledValuesPlug() const;

bool canAddInput( const ValuePlug *prototype ) const;
ValuePlug *addInput( const ValuePlug *prototype );
void removeInput( ValuePlug *inputPlug );

ValuePlug *outputPlugForInput( const ValuePlug *inputPlug );
const ValuePlug *outputPlugForInput( const ValuePlug *inputPlug ) const;

ValuePlug *inputPlugForOutput( const ValuePlug *outputPlug );
const ValuePlug *inputPlugForOutput( const ValuePlug *outputPlug ) const;

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

protected :

void hash( const ValuePlug *output, const Context *context, IECore::MurmurHash &h ) const override;
void compute( ValuePlug *output, const Context *context) const override;

ValuePlug::CachePolicy hashCachePolicy( const ValuePlug *output ) const override;
ValuePlug::CachePolicy computeCachePolicy( const ValuePlug *output ) const override;

private :

// We collect the values for all output plugs in a single compute and cache
// them in a CompoundObject on this internal plug, indexing them by plug name.
// This provides greater ValuePlug cache coherency when multiple inputs depend
// on the same upstream computes (for instance, when they are each collecting
// a property of the same scene location).
CompoundObjectPlug *collectionPlug();
const CompoundObjectPlug *collectionPlug() const;

void inputAdded( GraphComponent *input );
void inputRemoved( GraphComponent *input );
void inputNameChanged( GraphComponent *input, IECore::InternedString oldName );

std::unordered_map<GraphComponent *, Signals::ScopedConnection> m_inputNameChangedConnections;

static size_t g_firstPlugIndex;

};

} // namespace Gaffer
5 changes: 5 additions & 0 deletions include/Gaffer/PlugAlgo.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ GAFFER_API bool dependsOnCompute( const ValuePlug *plug );
template<typename Predicate>
std::invoke_result_t<Predicate, Plug *> findDestination( Plug *plug, Predicate &&predicate );

/// Visits the plug and its inputs, returing the first `predicate( plug )` result which
/// evaluates to `true`.
template<typename Predicate>
std::invoke_result_t<Predicate, Plug *> findSource( Plug *plug, Predicate &&predicate );

/// Conversion to and from `IECore::Data`
/// =====================================

Expand Down
16 changes: 16 additions & 0 deletions include/Gaffer/PlugAlgo.inl
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,20 @@ std::invoke_result_t<Predicate, Plug *> findDestination( Plug *plug, Predicate &
return std::invoke_result_t<Predicate, Plug *>();
}

template<typename Predicate>
std::invoke_result_t<Predicate, Plug *> findSource( Plug *plug, Predicate &&predicate )
{
while( plug )
{
if( auto source = predicate( plug ) )
{
return source;
}
plug = plug->getInput();
}

// Typically a null pointer.
return std::invoke_result_t<Predicate, Plug *>();
}

} // namespace Gaffer::PlugAlgo
1 change: 1 addition & 0 deletions include/Gaffer/TypeIds.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ enum TypeId
HiddenFilePathFilterTypeId = 110105,
Color4fVectorDataPlugTypeId = 110106,
OptionalValuePlugTypeId = 110107,
CollectTypeId = 110108,

LastTypeId = 110159,

Expand Down
Loading

0 comments on commit 32c42d9

Please sign in to comment.