Files
Andron666 9c38e93fa4 part7
2022-12-05 20:31:35 +05:00

969 lines
26 KiB
C++

/*
* Copyright (c) <2021> Side Effects Software Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. The name of Side Effects Software may not be used to endorse or
* promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE "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 SIDE EFFECTS SOFTWARE 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.
*/
#include "HoudiniParameterRamp.h"
#include "HoudiniParameter.h"
#include "HoudiniParameterFloat.h"
#include "HoudiniParameterColor.h"
#include "HoudiniParameterChoice.h"
#include "UObject/UnrealType.h"
void
UHoudiniParameterRampFloatPoint::SetPosition(const float InPosition)
{
if (PositionParentParm && PositionParentParm->GetNumberOfValues() > 0)
{
Position = InPosition;
PositionParentParm->SetValueAt(InPosition, 0);
PositionParentParm->SetIsChildOfRamp();
}
};
void
UHoudiniParameterRampFloatPoint::SetValue(const float InValue)
{
if (ValueParentParm && PositionParentParm->GetNumberOfValues() > 0)
{
Value = InValue;
ValueParentParm->SetValueAt(InValue, 0);
ValueParentParm->SetIsChildOfRamp();
}
};
void
UHoudiniParameterRampFloatPoint::SetInterpolation(const EHoudiniRampInterpolationType InInterpolation)
{
if (InterpolationParentParm)
{
Interpolation = InInterpolation;
InterpolationParentParm->SetIntValue((int32)InInterpolation);
InterpolationParentParm->UpdateStringValueFromInt();
InterpolationParentParm->SetIsChildOfRamp();
}
}
UHoudiniParameterRampFloatPoint*
UHoudiniParameterRampFloatPoint::DuplicateAndCopyState(UObject* DestOuter, EObjectFlags InClearFlags, EObjectFlags InSetFlags)
{
UHoudiniParameterRampFloatPoint* NewPoint = Cast<UHoudiniParameterRampFloatPoint>(StaticDuplicateObject(this, DestOuter));
NewPoint->CopyStateFrom(this, false, InClearFlags, InSetFlags);
return NewPoint;
}
void
UHoudiniParameterRampFloatPoint::CopyStateFrom(UHoudiniParameterRampFloatPoint * InParameter, bool bCopyAllProperties, EObjectFlags InClearFlags, EObjectFlags InSetFlags)
{
if (bCopyAllProperties)
{
UEngine::FCopyPropertiesForUnrelatedObjectsParams Params;
Params.bDoDelta = false; // Perform a deep copy
Params.bClearReferences = false; // References will be replaced afterwards.
UEngine::CopyPropertiesForUnrelatedObjects(InParameter, this, Params);
}
// Ensure this object's flags match the desired flags.
if (InClearFlags != RF_NoFlags)
ClearFlags( InClearFlags );
if (InSetFlags != RF_NoFlags)
SetFlags(InSetFlags);
}
void
UHoudiniParameterRampFloatPoint::RemapParameters(
const TMap<UHoudiniParameter*, UHoudiniParameter*>& ParameterMapping)
{
if (ParameterMapping.Contains(PositionParentParm))
{
PositionParentParm = CastChecked<UHoudiniParameterFloat>(ParameterMapping.FindChecked(PositionParentParm));
}
else
{
PositionParentParm = nullptr;
}
if (ParameterMapping.Contains(ValueParentParm))
{
ValueParentParm = CastChecked<UHoudiniParameterFloat>(ParameterMapping.FindChecked(ValueParentParm));
}
else
{
ValueParentParm = nullptr;
}
if (ParameterMapping.Contains(InterpolationParentParm))
{
InterpolationParentParm = CastChecked<UHoudiniParameterChoice>(ParameterMapping.FindChecked(InterpolationParentParm));
}
else
{
InterpolationParentParm = nullptr;
}
};
void
UHoudiniParameterRampColorPoint::SetPosition(const float InPosition)
{
if (PositionParentParm && PositionParentParm->GetNumberOfValues() > 0)
{
Position = InPosition;
PositionParentParm->SetValueAt(InPosition, 0);
PositionParentParm->SetIsChildOfRamp();
}
};
void
UHoudiniParameterRampColorPoint::SetValue(const FLinearColor InValue)
{
if (!ValueParentParm)
return;
Value = InValue;
ValueParentParm->SetColorValue(InValue);
ValueParentParm->SetIsChildOfRamp();
};
void
UHoudiniParameterRampColorPoint::SetInterpolation(const EHoudiniRampInterpolationType InInterpolation)
{
if (!InterpolationParentParm)
return;
Interpolation = InInterpolation;
InterpolationParentParm->SetIntValue((int32)InInterpolation);
InterpolationParentParm->UpdateStringValueFromInt();
InterpolationParentParm->SetIsChildOfRamp();
}
UHoudiniParameterRampColorPoint * UHoudiniParameterRampColorPoint::DuplicateAndCopyState(UObject * DestOuter, EObjectFlags InClearFlags, EObjectFlags InSetFlags)
{
UHoudiniParameterRampColorPoint* NewPoint = Cast<UHoudiniParameterRampColorPoint>(StaticDuplicateObject(this, DestOuter));
NewPoint->CopyStateFrom(this, false, InClearFlags, InSetFlags);
return NewPoint;
}
void UHoudiniParameterRampColorPoint::CopyStateFrom(UHoudiniParameterRampColorPoint * InParameter, bool bCopyAllProperties, EObjectFlags InClearFlags, EObjectFlags InSetFlags)
{
#if WITH_EDITOR
PreEditChange(nullptr);
#endif
if (bCopyAllProperties)
{
UEngine::FCopyPropertiesForUnrelatedObjectsParams Params;
Params.bDoDelta = false; // Perform a deep copy
Params.bClearReferences = false; // References will be replaced afterwards.
UEngine::CopyPropertiesForUnrelatedObjects(InParameter, this, Params);
}
// Ensure this object's flags match the desired flags.
if (InClearFlags != RF_NoFlags)
ClearFlags( InClearFlags );
if (InSetFlags != RF_NoFlags)
SetFlags(InSetFlags);
#if WITH_EDITOR
PostEditChange();
#endif
}
void UHoudiniParameterRampColorPoint::RemapParameters(const TMap<UHoudiniParameter*, UHoudiniParameter*>& ParameterMapping)
{
if (ParameterMapping.Contains(PositionParentParm))
{
PositionParentParm = CastChecked<UHoudiniParameterFloat>(ParameterMapping.FindChecked(PositionParentParm));
}
else
{
PositionParentParm = nullptr;
}
if (ParameterMapping.Contains(ValueParentParm))
{
ValueParentParm = CastChecked<UHoudiniParameterColor>(ParameterMapping.FindChecked(ValueParentParm));
}
else
{
ValueParentParm = nullptr;
}
if (ParameterMapping.Contains(InterpolationParentParm))
{
InterpolationParentParm = CastChecked<UHoudiniParameterChoice>(ParameterMapping.FindChecked(InterpolationParentParm));
}
else
{
InterpolationParentParm = nullptr;
}
}
UHoudiniParameterRampFloat::UHoudiniParameterRampFloat(const FObjectInitializer & ObjectInitializer)
: Super(ObjectInitializer),
NumDefaultPoints(-1),
bCaching(false)
{
ParmType = EHoudiniParameterType::FloatRamp;
}
void
UHoudiniParameterRampFloat::OnPreCook()
{
if (bCaching)
{
SyncCachedPoints();
bCaching = false;
}
}
UHoudiniParameterRampFloat *
UHoudiniParameterRampFloat::Create(
UObject* InOuter,
const FString& InParamName)
{
FString ParamNameStr = "HoudiniParameterRamp_" + InParamName;
FName ParamName = MakeUniqueObjectName(InOuter, UHoudiniParameterRampFloat::StaticClass(), *ParamNameStr);
// We need to create a new parameter
UHoudiniParameterRampFloat * HoudiniParameter = NewObject< UHoudiniParameterRampFloat >(
InOuter, UHoudiniParameterRampFloat::StaticClass(), ParamName, RF_Public | RF_Transactional);
HoudiniParameter->SetParameterType(EHoudiniParameterType::FloatRamp);
HoudiniParameter->NumDefaultPoints = -1;
HoudiniParameter->bCaching = false;
return HoudiniParameter;
}
void UHoudiniParameterRampFloat::CopyStateFrom(UHoudiniParameter* InParameter, bool bCopyAllProperties, EObjectFlags InClearFlags, EObjectFlags InSetFlags)
{
#if WITH_EDITOR
PreEditChange(nullptr);
#endif
UHoudiniParameterRampFloat* FromParameter = Cast<UHoudiniParameterRampFloat>(InParameter);
check(FromParameter);
TArray<UHoudiniParameterRampFloatPoint*> PrevCachedPoints = CachedPoints;
TArray<UHoudiniParameterRampFloatPoint*> PrevPoints = Points;
Super::CopyStateFrom(InParameter, bCopyAllProperties, InClearFlags, InSetFlags);
CachedPoints = PrevCachedPoints;
Points = PrevPoints;
auto CopyPointsStateFn = [InClearFlags, InSetFlags] (TArray<UHoudiniParameterRampFloatPoint*>& FromArray, TArray<UHoudiniParameterRampFloatPoint*>& ToArray, UObject* NewOuter)
{
const int32 NumPts = FromArray.Num();
ToArray.SetNum(NumPts);
for(int32 i = 0; i < NumPts; ++i)
{
UHoudiniParameterRampFloatPoint* FromPoint = FromArray[i];
UHoudiniParameterRampFloatPoint* ToPoint = ToArray[i];
check(FromPoint);
if (ToPoint)
{
// Ensure the destination point is outered to this parameter
bool bIsValid = ToPoint->GetOuter() == NewOuter;
if (!bIsValid)
ToPoint = nullptr;
}
if (!ToPoint)
{
// Duplicate a new copy using FromPoint
ToPoint = FromPoint->DuplicateAndCopyState(NewOuter, InClearFlags, InSetFlags);
}
else
{
// We have a valid point that we can reuse. Simply copy state.
ToPoint->CopyStateFrom(FromPoint, true, InClearFlags, InSetFlags);
}
ToArray[i] = ToPoint;
}
};
CopyPointsStateFn(FromParameter->CachedPoints, CachedPoints, this);
CopyPointsStateFn(FromParameter->Points, Points, this);
#if WITH_EDITOR
PostEditChange();
#endif
}
void
UHoudiniParameterRampFloat::RemapParameters(const TMap<UHoudiniParameter*, UHoudiniParameter*>& ParameterMapping)
{
Super::RemapParameters(ParameterMapping);
AActor* OuterActor = GetTypedOuter<AActor>();
for(UHoudiniParameterRampFloatPoint* CurrentPoint : Points)
{
CurrentPoint->RemapParameters(ParameterMapping);
}
for(UHoudiniParameterRampFloatPoint* CurrentPoint : CachedPoints)
{
CurrentPoint->RemapParameters(ParameterMapping);
}
}
void
UHoudiniParameterRampFloat::SyncCachedPoints()
{
int32 Idx = 0;
while (Idx < CachedPoints.Num() && Idx < Points.Num())
{
UHoudiniParameterRampFloatPoint* &CachedPoint = CachedPoints[Idx];
UHoudiniParameterRampFloatPoint* &CurrentPoint = Points[Idx];
if (!CachedPoint || !CurrentPoint)
continue;
if (CachedPoint->GetPosition() != CurrentPoint->GetPosition())
{
if (CurrentPoint->PositionParentParm)
{
CurrentPoint->SetPosition(CachedPoint->GetPosition());
CurrentPoint->PositionParentParm->MarkChanged(true);
}
}
if (CachedPoint->GetValue() != CurrentPoint->GetValue())
{
if (CurrentPoint->ValueParentParm)
{
CurrentPoint->SetValue(CachedPoint->GetValue());
CurrentPoint->ValueParentParm->MarkChanged(true);
}
}
if (CachedPoint->GetInterpolation() != CurrentPoint->GetInterpolation())
{
if (CurrentPoint->InterpolationParentParm)
{
CurrentPoint->SetInterpolation(CachedPoint->GetInterpolation());
CurrentPoint->InterpolationParentParm->MarkChanged(true);
}
}
Idx += 1;
}
// Insert points
for (int32 IdxCachedPointLeft = Idx; IdxCachedPointLeft < CachedPoints.Num(); ++IdxCachedPointLeft)
{
UHoudiniParameterRampFloatPoint *&CachedPoint = CachedPoints[IdxCachedPointLeft];
if (!CachedPoint)
continue;
CreateInsertEvent(CachedPoint->Position, CachedPoint->Value, CachedPoint->Interpolation);
MarkChanged(true);
}
// Remove points
for (int32 IdxCurrentPointLeft = Idx; IdxCurrentPointLeft < Points.Num(); ++IdxCurrentPointLeft)
{
RemoveElement(IdxCurrentPointLeft);
UHoudiniParameterRampFloatPoint* Point = Points[IdxCurrentPointLeft];
if (!Point)
continue;
CreateDeleteEvent(Point->InstanceIndex);
MarkChanged(true);
}
}
void
UHoudiniParameterRampFloat::CreateInsertEvent(const float& InPosition, const float& InValue, const EHoudiniRampInterpolationType &InInterp)
{
UHoudiniParameterRampModificationEvent* InsertEvent = NewObject<UHoudiniParameterRampModificationEvent>(
this, UHoudiniParameterRampModificationEvent::StaticClass());
if (!InsertEvent)
return;
InsertEvent->SetFloatRampEvent();
InsertEvent->SetInsertEvent();
InsertEvent->InsertPosition = InPosition;
InsertEvent->InsertFloat = InValue;
InsertEvent->InsertInterpolation = InInterp;
ModificationEvents.Add(InsertEvent);
}
void
UHoudiniParameterRampFloat::CreateDeleteEvent(const int32 &InDeleteIndex)
{
UHoudiniParameterRampModificationEvent* DeleteEvent = NewObject<UHoudiniParameterRampModificationEvent>(
this, UHoudiniParameterRampModificationEvent::StaticClass());
if (!DeleteEvent)
return;
DeleteEvent->SetFloatRampEvent();
DeleteEvent->SetDeleteEvent();
DeleteEvent->DeleteInstanceIndex = InDeleteIndex;
ModificationEvents.Add(DeleteEvent);
}
bool
UHoudiniParameterRampFloat::UpdatePointsArray(const TArray<UHoudiniParameter*>& InParameters, const int32 InStartParamIndex)
{
// Copy existing points to NewPoints
TArray<UHoudiniParameterRampFloatPoint*> NewPoints;
const int32 NumInstances = GetInstanceCount();
NewPoints.Reserve(NumInstances);
for (UHoudiniParameterRampFloatPoint* const PointData : Points)
{
if (!IsValid(PointData))
continue;
PointData->InstanceIndex = NewPoints.Num();
PointData->PositionParentParm = nullptr;
PointData->ValueParentParm = nullptr;
PointData->InterpolationParentParm = nullptr;
NewPoints.Add(PointData);
// We don't need more than NumInstances points in the array
if (NewPoints.Num() == NumInstances)
break;
}
// Loop over InParameters and look for children of this ramp
int32 CurrentInstanceIndex = 0;
const int32 NumParameters = InParameters.Num();
for (int32 Index = InStartParamIndex; Index < NumParameters; ++Index)
{
UHoudiniParameter* const Param = InParameters[Index];
if (!IsValid(Param))
continue;
if (!Param->GetIsChildOfMultiParm() || Param->GetParentParmId() != ParmId)
continue;
const EHoudiniParameterType ParamType = Param->GetParameterType();
if (ParamType != EHoudiniParameterType::Float && ParamType != EHoudiniParameterType::IntChoice)
continue;
// Ensure we have a valid point object at the current index
UHoudiniParameterRampFloatPoint* Point = nullptr;
if (!NewPoints.IsValidIndex(CurrentInstanceIndex))
{
Point = NewObject<UHoudiniParameterRampFloatPoint>(this, FName(), this->GetMaskedFlags(RF_PropagateToSubObjects));
Point->InstanceIndex = CurrentInstanceIndex;
NewPoints.Add(Point);
}
else
{
Point = NewPoints[CurrentInstanceIndex];
}
if (ParamType == EHoudiniParameterType::Float)
{
UHoudiniParameterFloat* FloatParameter = Cast<UHoudiniParameterFloat>(Param);
if (FloatParameter)
{
//*****Float Parameter (position)*****//
if (!Point->PositionParentParm)
{
if (FloatParameter->GetNumberOfValues() <= 0)
continue;
// Set the float ramp point's position parent parm, and value
Point->PositionParentParm = FloatParameter;
Point->SetPosition(FloatParameter->GetValuesPtr()[0]);
}
//*****Float Parameter (value)*****//
else
{
if (FloatParameter->GetNumberOfValues() <= 0)
continue;;
Point->ValueParentParm = FloatParameter;
Point->SetValue(FloatParameter->GetValuesPtr()[0]);
}
}
}
//*****Choice parameter (Interpolation)*****//
else if (ParamType == EHoudiniParameterType::IntChoice)
{
UHoudiniParameterChoice* ChoiceParameter = Cast<UHoudiniParameterChoice>(Param);
if (ChoiceParameter)
{
Point->InterpolationParentParm = ChoiceParameter;
Point->SetInterpolation(UHoudiniParameter::GetHoudiniInterpMethodFromInt(ChoiceParameter->GetIntValueIndex()));
CurrentInstanceIndex++;
}
}
}
//*****All ramp points have been parsed, finish!*****//
if (NewPoints.Num() == NumInstances)
{
NewPoints.Sort([](const UHoudiniParameterRampFloatPoint& P1, const UHoudiniParameterRampFloatPoint& P2) {
return P1.Position < P2.Position;
});
Points = MoveTemp(NewPoints);
// Not caching, points are synced, update cached points
if (!bCaching)
{
const int32 NumPoints = Points.Num();
CachedPoints.SetNumZeroed(NumPoints);
for (int32 i = 0; i < NumPoints; ++i)
{
UHoudiniParameterRampFloatPoint* const FromPoint = Points[i];
UHoudiniParameterRampFloatPoint* ToPoint = CachedPoints[i];
// Nothing we can do/copy if FromPoint is null/pending kill
if (!IsValid(FromPoint))
continue;
if (!IsValid(ToPoint))
{
ToPoint = FromPoint->DuplicateAndCopyState(this, RF_NoFlags, GetMaskedFlags(RF_PropagateToSubObjects));
CachedPoints[i] = ToPoint;
}
else
{
ToPoint->CopyStateFrom(FromPoint, true);
}
}
}
SetDefaultValues();
return true;
}
return false;
}
UHoudiniParameterRampColor::UHoudiniParameterRampColor(const FObjectInitializer & ObjectInitializer)
: Super(ObjectInitializer),
bCaching(false),
NumDefaultPoints(-1)
{
ParmType = EHoudiniParameterType::ColorRamp;
}
UHoudiniParameterRampColor *
UHoudiniParameterRampColor::Create(
UObject* InOuter,
const FString& InParamName)
{
FString ParamNameStr = "HoudiniParameterRamp_" + InParamName;
FName ParamName = MakeUniqueObjectName(InOuter, UHoudiniParameterRampColor::StaticClass(), *ParamNameStr);
// We need to create a new parameter
UHoudiniParameterRampColor * HoudiniParameter = NewObject< UHoudiniParameterRampColor >(
InOuter, UHoudiniParameterRampColor::StaticClass(), ParamName, RF_Public | RF_Transactional);
HoudiniParameter->SetParameterType(EHoudiniParameterType::ColorRamp);
HoudiniParameter->NumDefaultPoints = -1;
HoudiniParameter->bCaching = false;
return HoudiniParameter;
}
bool
UHoudiniParameterRampFloat::IsDefault() const
{
if (NumDefaultPoints < 0)
return true;
if (NumDefaultPoints != Points.Num())
{
return false;
}
TArray<float> Positions = DefaultPositions;
TArray<float> Values = DefaultValues;
TArray<int32> Choices = DefaultChoices;
for (auto & NextPt : Points)
{
if (!NextPt)
return false;
bool bFoundMatch = false;
for (int32 DefaultIdx = 0; DefaultIdx < Positions.Num(); ++DefaultIdx)
{
if (Positions[DefaultIdx] == NextPt->Position &&
Values[DefaultIdx] == NextPt->Value &&
Choices[DefaultIdx] == (int32)NextPt->Interpolation)
{
Positions.RemoveAt(DefaultIdx);
Values.RemoveAt(DefaultIdx);
Choices.RemoveAt(DefaultIdx);
bFoundMatch = true;
}
}
if (!bFoundMatch)
return false;
}
if (Positions.Num() > 0)
return false;
return true;
}
void UHoudiniParameterRampColor::CopyStateFrom(UHoudiniParameter * InParameter, bool bCopyAllProperties, EObjectFlags InClearFlags, EObjectFlags InSetFlags)
{
UHoudiniParameterRampColor* FromParameter = Cast<UHoudiniParameterRampColor>(InParameter);
check(FromParameter);
TArray<UHoudiniParameterRampColorPoint*> PrevCachedPoints = CachedPoints;
TArray<UHoudiniParameterRampColorPoint*> PrevPoints = Points;
Super::CopyStateFrom(InParameter, bCopyAllProperties, InClearFlags, InSetFlags);
CachedPoints = PrevCachedPoints;
Points = PrevPoints;
auto CopyPointsStateFn = [InClearFlags, InSetFlags] (TArray<UHoudiniParameterRampColorPoint*>& FromArray, TArray<UHoudiniParameterRampColorPoint*>& ToArray, UObject* NewOuter)
{
const int32 NumPts = FromArray.Num();
ToArray.SetNum(NumPts);
for(int32 i = 0; i < NumPts; ++i)
{
UHoudiniParameterRampColorPoint* FromPoint = FromArray[i];
UHoudiniParameterRampColorPoint* ToPoint = ToArray[i];
check(FromPoint);
if (ToPoint)
{
// Ensure the destination point is outered to this parameter
bool bIsValid = ToPoint->GetOuter() == NewOuter;
if (!bIsValid)
ToPoint = nullptr;
}
if (!ToPoint)
{
// Duplicate a new copy using FromPoint
ToPoint = FromPoint->DuplicateAndCopyState(NewOuter, InClearFlags, InSetFlags);
}
else
{
// We have a valid point that we can reuse. Simply copy state.
ToPoint->CopyStateFrom(FromPoint, true, InClearFlags, InSetFlags);
}
ToArray[i] = ToPoint;
}
};
CopyPointsStateFn(FromParameter->CachedPoints, CachedPoints, this);
CopyPointsStateFn(FromParameter->Points, Points, this);
if (InClearFlags != RF_NoFlags)
ClearFlags( InClearFlags );
if (InSetFlags != RF_NoFlags)
SetFlags(InSetFlags);
}
void UHoudiniParameterRampColor::RemapParameters(const TMap<UHoudiniParameter*, UHoudiniParameter*>& ParameterMapping)
{
Super::RemapParameters(ParameterMapping);
AActor* OuterActor = GetTypedOuter<AActor>();
for(UHoudiniParameterRampColorPoint* CurrentPoint : Points)
{
CurrentPoint->RemapParameters(ParameterMapping);
}
for(UHoudiniParameterRampColorPoint* CurrentPoint : CachedPoints)
{
CurrentPoint->RemapParameters(ParameterMapping);
}
}
bool
UHoudiniParameterRampColor::UpdatePointsArray(const TArray<UHoudiniParameter*>& InParameters, const int32 InStartParamIndex)
{
// Copy existing points to NewPoints
TArray<UHoudiniParameterRampColorPoint*> NewPoints;
const int32 NumInstances = GetInstanceCount();
NewPoints.Reserve(NumInstances);
for (UHoudiniParameterRampColorPoint* const PointData : Points)
{
if (!IsValid(PointData))
continue;
PointData->InstanceIndex = NewPoints.Num();
PointData->PositionParentParm = nullptr;
PointData->ValueParentParm = nullptr;
PointData->InterpolationParentParm = nullptr;
NewPoints.Add(PointData);
// We don't need more than NumInstances points in the array
if (NewPoints.Num() == NumInstances)
break;
}
// Loop over InParameters and look for children of this ramp
int32 CurrentInstanceIndex = 0;
const int32 NumParameters = InParameters.Num();
for (int32 Index = InStartParamIndex; Index < NumParameters; ++Index)
{
UHoudiniParameter* const Param = InParameters[Index];
if (!IsValid(Param))
continue;
if (!Param->GetIsChildOfMultiParm() || Param->GetParentParmId() != ParmId)
continue;
const EHoudiniParameterType ParamType = Param->GetParameterType();
if (ParamType != EHoudiniParameterType::Float && ParamType != EHoudiniParameterType::Color &&
ParamType != EHoudiniParameterType::IntChoice)
continue;
// Ensure we have a valid point object at the current index
UHoudiniParameterRampColorPoint* Point = nullptr;
if (!NewPoints.IsValidIndex(CurrentInstanceIndex))
{
Point = NewObject<UHoudiniParameterRampColorPoint>(this, FName(), this->GetMaskedFlags(RF_PropagateToSubObjects));
Point->InstanceIndex = CurrentInstanceIndex;
NewPoints.Add(Point);
}
else
{
Point = NewPoints[CurrentInstanceIndex];
}
if (ParamType == EHoudiniParameterType::Float)
{
UHoudiniParameterFloat* FloatParameter = Cast<UHoudiniParameterFloat>(Param);
if (FloatParameter)
{
//*****Float Parameter (position)*****//
if (!Point->PositionParentParm)
{
if (FloatParameter->GetNumberOfValues() <= 0)
continue;
// Set the float ramp point's position parent parm, and value
Point->PositionParentParm = FloatParameter;
Point->SetPosition(FloatParameter->GetValuesPtr()[0]);
}
}
}
else if (ParamType == EHoudiniParameterType::Color)
{
UHoudiniParameterColor* ColorParameter = Cast<UHoudiniParameterColor>(Param);
if (ColorParameter)
{
//*****Color Parameter (value)*****//
Point->ValueParentParm = ColorParameter;
Point->SetValue(ColorParameter->GetColorValue());
}
}
//*****Choice parameter (Interpolation)*****//
else if (ParamType == EHoudiniParameterType::IntChoice)
{
UHoudiniParameterChoice* ChoiceParameter = Cast<UHoudiniParameterChoice>(Param);
if (ChoiceParameter)
{
Point->InterpolationParentParm = ChoiceParameter;
Point->SetInterpolation(UHoudiniParameter::GetHoudiniInterpMethodFromInt(ChoiceParameter->GetIntValueIndex()));
CurrentInstanceIndex++;
}
}
}
//*****All ramp points have been parsed, finish!*****//
if (NewPoints.Num() == NumInstances)
{
NewPoints.Sort([](const UHoudiniParameterRampColorPoint& P1, const UHoudiniParameterRampColorPoint& P2) {
return P1.Position < P2.Position;
});
Points = MoveTemp(NewPoints);
// Not caching, points are synced, update cached points
if (!bCaching)
{
const int32 NumPoints = Points.Num();
CachedPoints.SetNumZeroed(NumPoints);
for (int32 i = 0; i < NumPoints; ++i)
{
UHoudiniParameterRampColorPoint* const FromPoint = Points[i];
UHoudiniParameterRampColorPoint* ToPoint = CachedPoints[i];
// Nothing we can do/copy if FromPoint is null/pending kill
if (!IsValid(FromPoint))
continue;
if (!IsValid(ToPoint))
{
ToPoint = FromPoint->DuplicateAndCopyState(this, RF_NoFlags, GetMaskedFlags(RF_PropagateToSubObjects));
CachedPoints[i] = ToPoint;
}
else
{
ToPoint->CopyStateFrom(FromPoint, true);
}
}
}
SetDefaultValues();
return true;
}
return false;
}
bool
UHoudiniParameterRampColor::IsDefault() const
{
if (NumDefaultPoints < 0)
return true;
if (NumDefaultPoints != Points.Num())
return false;
TArray<float> Positions = DefaultPositions;
TArray<FLinearColor> Values = DefaultValues;
TArray<int32> Choices = DefaultChoices;
for (auto & NextPt : Points)
{
if (!NextPt)
return false;
bool bFoundMatch = false;
for (int32 DefaultIdx = 0; DefaultIdx < Positions.Num(); ++DefaultIdx)
{
if (Positions[DefaultIdx] == NextPt->Position &&
Values[DefaultIdx] == NextPt->Value &&
Choices[DefaultIdx] == (int32)NextPt->Interpolation)
{
Positions.RemoveAt(DefaultIdx);
Values.RemoveAt(DefaultIdx);
Choices.RemoveAt(DefaultIdx);
bFoundMatch = true;
}
}
if (!bFoundMatch)
return false;
}
if (Positions.Num() > 0)
return false;
return true;
}
void
UHoudiniParameterRampColor::SetDefaultValues()
{
if (NumDefaultPoints >= 0)
return;
if (DefaultPositions.Num() > 0)
return;
DefaultPositions.Empty();
DefaultValues.Empty();
DefaultChoices.Empty();
for (auto & NextPoint : Points)
{
if (!NextPoint)
continue;
DefaultPositions.Add(NextPoint->Position);
DefaultValues.Add(NextPoint->Value);
DefaultChoices.Add((int32)NextPoint->Interpolation);
}
NumDefaultPoints = Points.Num();
}
void
UHoudiniParameterRampFloat::SetDefaultValues()
{
if (DefaultPositions.Num() > 0)
return;
DefaultPositions.Empty();
DefaultValues.Empty();
DefaultChoices.Empty();
for (auto & NextPoint : Points)
{
if (!NextPoint)
continue;
DefaultPositions.Add(NextPoint->Position);
DefaultValues.Add(NextPoint->Value);
DefaultChoices.Add((int32)NextPoint->Interpolation);
}
NumDefaultPoints = Points.Num();
}