Skip to content

Commit

Permalink
TweakPlug : Experimental refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
danieldresser-ie committed Nov 22, 2024
1 parent 0e3ec4a commit b799b57
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 83 deletions.
9 changes: 9 additions & 0 deletions include/Gaffer/TweakPlug.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ class GAFFER_API TweakPlug : public Gaffer::ValuePlug
MissingMode missingMode = MissingMode::Error
) const;

template< typename T >
static void applyNumericTweakValue(
const T &source,
const T &tweak,
T &dest,
TweakPlug::Mode mode,
const std::string &tweakName
);

private :

Gaffer::ValuePlug *valuePlugInternal();
Expand Down
93 changes: 93 additions & 0 deletions include/Gaffer/TweakPlug.inl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@

#include "Gaffer/PlugAlgo.h"

#include "IECore/TypeTraits.h"

#include "fmt/format.h"

namespace Gaffer
Expand Down Expand Up @@ -179,4 +181,95 @@ bool TweaksPlug::applyTweaks(
return tweakApplied;
}

template<typename T>
T vectorAwareMin( const T &v1, const T &v2 )
{
if constexpr( IECore::TypeTraits::IsVec<T>::value || IECore::TypeTraits::IsColor<T>::value )
{
T result;
for( size_t i = 0; i < T::dimensions(); ++i )
{
result[i] = std::min( v1[i], v2[i] );
}
return result;
}
else
{
return std::min( v1, v2 );
}
}

template<typename T>
T vectorAwareMax( const T &v1, const T &v2 )
{
if constexpr( IECore::TypeTraits::IsVec<T>::value || IECore::TypeTraits::IsColor<T>::value )
{
T result;
for( size_t i = 0; i < T::dimensions(); ++i )
{
result[i] = std::max( v1[i], v2[i] );
}
return result;
}
else
{
return std::max( v1, v2 );
}
}

template< typename T >
void TweakPlug::applyNumericTweakValue(
const T &source,
const T &tweak,
T &dest,
TweakPlug::Mode mode,
const std::string &tweakName
)
{
if constexpr(
( std::is_arithmetic_v<T> && !std::is_same_v< T, bool > ) ||
IECore::TypeTraits::IsVec<T>::value ||
IECore::TypeTraits::IsColor<T>::value
) {
switch( mode )
{
case TweakPlug::Add :
dest = source + tweak;
break;
case TweakPlug::Subtract :
dest = source - tweak;
break;
case TweakPlug::Multiply :
dest = source * tweak;
break;
case TweakPlug::Min :
dest = vectorAwareMin( source, tweak );
break;
case TweakPlug::Max :
dest = vectorAwareMax( source, tweak );
break;
case TweakPlug::ListAppend :
case TweakPlug::ListPrepend :
case TweakPlug::ListRemove :
case TweakPlug::Replace :
case TweakPlug::Remove :
case TweakPlug::Create :
case TweakPlug::CreateIfMissing :
// These cases are unused - we handle them outside of numericTweak.
// But the compiler gets unhappy if we don't handle some cases.
assert( false );
break;
}
}
else
{
throw IECore::Exception(
fmt::format(
"Cannot apply tweak with mode {} to \"{}\" : Data type {} not supported.",
modeToString( mode ), tweakName, "foo" //sourceData->typeName()
)
);
}
}

} // namespace Gaffer
88 changes: 5 additions & 83 deletions src/Gaffer/TweakPlug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,50 +63,6 @@ using namespace Gaffer;
namespace
{

/// \todo - if these make sense, I guess they should be pushed back to cortex

// IsColorTypedData
template< typename T > struct IsColorTypedData : boost::mpl::and_< TypeTraits::IsTypedData<T>, TypeTraits::IsColor< typename TypeTraits::ValueType<T>::type > > {};

// SupportsArithmeticData
template< typename T > struct SupportsArithData : boost::mpl::or_< TypeTraits::IsNumericSimpleTypedData<T>, TypeTraits::IsVecTypedData<T>, IsColorTypedData<T>> {};

template<typename T>
T vectorAwareMin( const T &v1, const T &v2 )
{
if constexpr( TypeTraits::IsVec<T>::value || TypeTraits::IsColor<T>::value )
{
T result;
for( size_t i = 0; i < T::dimensions(); ++i )
{
result[i] = std::min( v1[i], v2[i] );
}
return result;
}
else
{
return std::min( v1, v2 );
}
}

template<typename T>
T vectorAwareMax( const T &v1, const T &v2 )
{
if constexpr( TypeTraits::IsVec<T>::value || TypeTraits::IsColor<T>::value )
{
T result;
for( size_t i = 0; i < T::dimensions(); ++i )
{
result[i] = std::max( v1[i], v2[i] );
}
return result;
}
else
{
return std::max( v1, v2 );
}
}

template<typename T>
vector<T> tweakedList( const std::vector<T> &source, const std::vector<T> &tweak, TweakPlug::Mode mode )
{
Expand Down Expand Up @@ -317,48 +273,14 @@ void TweakPlug::applyNumericTweak(

using DataType = typename std::remove_pointer<decltype( data )>::type;

if constexpr( SupportsArithData<DataType>::value ) {

if constexpr( TypeTraits::IsTypedData< DataType >::value )
{
const DataType *sourceDataCast = runTimeCast<const DataType>( sourceData );
const DataType *tweakDataCast = runTimeCast<const DataType>( tweakData );

switch( mode )
{
case TweakPlug::Add :
data->writable() = sourceDataCast->readable() + tweakDataCast->readable();
break;
case TweakPlug::Subtract :
data->writable() = sourceDataCast->readable() - tweakDataCast->readable();
break;
case TweakPlug::Multiply :
data->writable() = sourceDataCast->readable() * tweakDataCast->readable();
break;
case TweakPlug::Min :
data->writable() = vectorAwareMin( sourceDataCast->readable(), tweakDataCast->readable() );
break;
case TweakPlug::Max :
data->writable() = vectorAwareMax( sourceDataCast->readable(), tweakDataCast->readable() );
break;
case TweakPlug::ListAppend :
case TweakPlug::ListPrepend :
case TweakPlug::ListRemove :
case TweakPlug::Replace :
case TweakPlug::Remove :
case TweakPlug::Create :
case TweakPlug::CreateIfMissing :
// These cases are unused - we handle them outside of numericTweak.
// But the compiler gets unhappy if we don't handle some cases.
assert( false );
break;
}
}
else
{
throw IECore::Exception(
fmt::format(
"Cannot apply tweak with mode {} to \"{}\" : Data type {} not supported.",
modeToString( mode ), tweakName, sourceData->typeName()
)
applyNumericTweakValue(
sourceDataCast->readable(), tweakDataCast->readable(), data->writable(),
mode, tweakName
);
}
}
Expand Down

0 comments on commit b799b57

Please sign in to comment.