Files
UnrealEngineUWP/Engine/Plugins/Runtime/MeshModelingToolset/Source/ModelingComponents/Public/Changes/IndexedAttributeChange.h
michael balzer a49c74b915 MeshModelingToolset: Move ModelingOperators and ModelingOperatorsEditorOnly modules out of experimental plugin
#jira UETOOL-3823
#rb lonnie.li
#preflight 617b1aea5794a500014f544a

#ROBOMERGE-AUTHOR: michael.balzer
#ROBOMERGE-SOURCE: CL 17972239 in //UE5/Release-5.0/... via CL 17972248
#ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v885-17909292)
#ROBOMERGE[STARSHIP]: UE5-Main

[CL 17972256 by michael balzer in ue5-release-engine-test branch]
2021-10-28 19:47:45 -04:00

129 lines
3.5 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "InteractiveToolChange.h"
/**
* TIndexedValuesChange stores a change of values at a set of indices.
* For example if you were changing positions of vertices of a mesh, you could
* use this change to store the new and old positions.
*
* This is an abstract base class, you must provide suitable Apply/Revert implementations.
* The TCustomIndexedValuesChange subclass will allow you to do this with lambdas.
*/
template<typename ValueType>
class TIndexedValuesChange : public FToolCommandChange
{
public:
TArray<int32> Indices;
TArray<ValueType> OldValues;
TArray<ValueType> NewValues;
virtual void Apply(UObject* Object) = 0;
virtual void Revert(UObject* Object) = 0;
virtual FString ToString() const override
{
return FString(TEXT("Indexed Values Change"));
}
};
/**
* TIndexedValuesChangeBuilder incrementally builds up a TIndexedValuesChange instance/subclass.
* The ChangeClassType template parameter should be the name of the TIndexedValuesChange-derived class.
*/
template<typename ValueType, typename ChangeClassType>
class TIndexedValuesChangeBuilder
{
public:
TUniquePtr<ChangeClassType> Change;
TMap<int32, int32> SavedIndices;
TIndexedValuesChangeBuilder()
{
}
/** Allocate a new change and start tracking */
void BeginNewChange()
{
Change = MakeUnique<ChangeClassType>();
SavedIndices.Reset();
}
/** Modify the value at an Index. Changes will be tracked as necessary. */
void UpdateValue(int32 Index, const ValueType& OldValue, const ValueType& NewValue)
{
check(Change.IsValid());
const int32* FoundIndex = SavedIndices.Find(Index);
if (FoundIndex == nullptr)
{
int32 NewIndex = Change->Indices.Num();
SavedIndices.Add(Index, NewIndex);
Change->Indices.Add(Index);
Change->OldValues.Add(OldValue);
Change->NewValues.Add(NewValue);
}
else
{
Change->NewValues[*FoundIndex] = NewValue;
}
}
/** Modify a set of values */
void UpdateValues(const TArray<int32>& Indices, const TArray<ValueType>& OldValues, const TArray<ValueType>& NewValues)
{
int32 NumIndices = Indices.Num();
for (int32 k = 0; k < NumIndices; ++k)
{
UpdateValue(Indices[k], OldValues[k], NewValues[k]);
}
}
/** Complete the change construction and return it */
TUniquePtr<ChangeClassType> ExtractResult()
{
return MoveTemp(Change);
}
};
/**
* TCustomIndexedValuesChange is an implementation of TIndexedValuesChange that allows you to
* provide the Apply() And Revert() implementations via lambdas, as well as specify a custom data
* element to be stored with the Change. For example if this is a change to an attribute array,
* you could store the attribute identifier in the CustomData.
*/
template<typename ValueType, typename CustomDataType>
class TCustomIndexedValuesChange : public TIndexedValuesChange<ValueType>
{
public:
using BaseType = TIndexedValuesChange<ValueType>;
CustomDataType CustomData;
TUniqueFunction<void(UObject*, const CustomDataType& Data, const TArray<int32>&, const TArray<ValueType>&)> ApplyFunction;
TUniqueFunction<void(UObject*, const CustomDataType& Data, const TArray<int32>&, const TArray<ValueType>&)> RevertFunction;
virtual void Apply(UObject* Object) override
{
if (ApplyFunction)
{
ApplyFunction(Object, CustomData, BaseType::Indices, BaseType::NewValues);
}
}
virtual void Revert(UObject* Object) override
{
if (RevertFunction)
{
RevertFunction(Object, CustomData, BaseType::Indices, BaseType::OldValues);
}
}
};