Files
UnrealEngine/Engine/Source/Editor/PhysicsAssetEditor/Private/PhysicsAssetEditorSelection.h
2025-05-18 13:04:45 +08:00

327 lines
11 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "PhysicsEngine/ShapeElem.h"
#include "Preferences/PhysicsAssetEditorOptions.h"
#include "PhysicsAssetEditorSelection.generated.h"
class UPhysicsAssetEditorSelection;
/** Encapsulates a selected set of bodies or constraints */
USTRUCT()
struct FPhysicsAssetEditorSelectedElement
{
GENERATED_BODY()
enum Type : int32
{
None,
Body = 1, // A physics body, comprised of one or more primitives.
CenterOfMass = 1 << 1, // A Center of Mass of a physics body.
Constraint = 1 << 2, // A constraint between two physics bodies.
Primitive = 1 << 3, // A primitive that defines the geometry of a physics body.
All = ~None
};
FPhysicsAssetEditorSelectedElement() = default;
FPhysicsAssetEditorSelectedElement(const Type InSelectedElementType, const int32 InBodyIndex, const EAggCollisionShape::Type InPrimitiveType, const int32 InPrimitiveIndex);
FPhysicsAssetEditorSelectedElement(const Type InSelectedElementType, const int32 InBodyIndex);
int32 GetIndex() const;
EAggCollisionShape::Type GetPrimitiveType() const;
int32 GetPrimitiveIndex() const;
Type GetElementType() const;
bool HasType(const uint32 InElementTypeFlags) const;
UPROPERTY()
int32 Index = INDEX_NONE;
UPROPERTY()
TEnumAsByte<EAggCollisionShape::Type> PrimitiveType = EAggCollisionShape::Unknown;
UPROPERTY()
int32 PrimitiveIndex = INDEX_NONE;
UPROPERTY()
int32 SelectedElementType = Type::None;
};
bool operator==(const FPhysicsAssetEditorSelectedElement& Lhs, const FPhysicsAssetEditorSelectedElement& Rhs);
bool IsReferencingPrimitive(const FPhysicsAssetEditorSelectedElement& InSelection, const int32 InBodyIndex, const EAggCollisionShape::Type InPrimitiveType, const int32 InPrimitiveIndex);
FPhysicsAssetEditorSelectedElement MakeBodySelection(TObjectPtr<UPhysicsAsset> InPhysicsAsset, const int32 InBodyIndex);
TArray<FPhysicsAssetEditorSelectedElement> MakeBodySelection(TObjectPtr<UPhysicsAsset> InPhysicsAsset, const TArray<int32> InBodyIndexCollection);
FPhysicsAssetEditorSelectedElement MakeCoMSelection(const int32 InCoMIndex);
FPhysicsAssetEditorSelectedElement MakeConstraintSelection(const int32 InConstraintIndex);
TArray<FPhysicsAssetEditorSelectedElement> MakeConstraintSelection(const TArray<int32>& Indices);
FPhysicsAssetEditorSelectedElement MakePrimitiveSelection(const int32 InBodyIndex, const EAggCollisionShape::Type InPrimitiveType, const int32 InPrimitiveIndex);
FPhysicsAssetEditorSelectedElement MakeSelectionAnyPrimitiveInBody(TObjectPtr<UPhysicsAsset> InPhysicsAsset, const int32 InBodyIndex); // Selected the 'first' primitive in the supplied body
TArray<FPhysicsAssetEditorSelectedElement> MakeSelectionAllPrimitivesInBody(TObjectPtr<UPhysicsAsset> InPhysicsAsset, const int32 InBodyIndex);
TArray<FPhysicsAssetEditorSelectedElement> MakeSelectionAllPrimitivesInBody(TObjectPtr<UPhysicsAsset> InPhysicsAsset, const TArray<int32> InBodyIndexCollection);
class FPhysicsAssetEditorSelectionIterator
{
public:
using Element = FPhysicsAssetEditorSelectedElement;
FPhysicsAssetEditorSelectionIterator();
FPhysicsAssetEditorSelectionIterator(const UPhysicsAssetEditorSelection* const InParentSelection);
FPhysicsAssetEditorSelectionIterator(const UPhysicsAssetEditorSelection* const InParentSelection, const uint32 InElementTypeFlags);
FPhysicsAssetEditorSelectionIterator(const UPhysicsAssetEditorSelection* const InParentSelection, const uint32 InElementTypeFlags, const uint32 InElementIndex);
FPhysicsAssetEditorSelectionIterator(const FPhysicsAssetEditorSelectionIterator& Other);
bool IsValid() const;
operator bool() const;
const Element& operator*();
const Element* operator->();
void operator++();
void operator--();
bool operator==(const FPhysicsAssetEditorSelectionIterator& Other) const;
uint32 GetElementTypeFlags() const;
uint32 GetIndexIntoFilteredSelection() const;
uint32 GetIndexIntoParentSelection() const;
const UPhysicsAssetEditorSelection* const GetParentSelection() const;
private:
void StepIndex(const bool bReverseDirection);
const Element& GetElement();
const UPhysicsAssetEditorSelection* const ParentSelection;
const uint32 ElementTypeFlags;
uint32 FilteredElementIndex;
uint32 ParentElementIndex;
};
template< typename IteratorType > class TPhysicsAssetEditorUniqueIterator
{
public:
using ThisType = TPhysicsAssetEditorUniqueIterator< IteratorType >;
using Iterator = IteratorType;
using Element = typename Iterator::Element;
TPhysicsAssetEditorUniqueIterator(Iterator InIterator);
bool IsValid() const;
operator bool() const;
const Element& operator*();
const Element* operator->();
void operator++();
void operator--();
bool operator==(const ThisType& Other) const;
private:
TArray<int32> EncounteredIndexIntoParentSelection;
IteratorType ManagedIterator;
};
template< typename IteratorType > class TPhysicsAssetEditorSelectionRange
{
public:
using Iterator = IteratorType;
using Element = Iterator::Element;
using TConstIterator = Iterator;
TPhysicsAssetEditorSelectionRange(Iterator InBegin, Iterator InEnd);
Iterator CreateConstIterator();
Iterator begin() const;
Iterator end() const;
bool IsValid() const;
operator bool() const;
bool IsEmpty() const;
int32 Num() const;
TArray<Element> ToArray();
const Element& At(const int32 InIndex) const;
private:
Iterator IteratorBegin;
Iterator IteratorEnd;
};
UCLASS()
class UPhysicsAssetEditorSelection : public UObject
{
public:
GENERATED_BODY()
using Element = FPhysicsAssetEditorSelectedElement;
using Selection = TArray< Element >;
using Iterator = FPhysicsAssetEditorSelectionIterator;
using FilterIterator = FPhysicsAssetEditorSelectionIterator;
using UniqueIterator = TPhysicsAssetEditorUniqueIterator< FilterIterator >;
using FilterRange = TPhysicsAssetEditorSelectionRange< FilterIterator >;
using UniqueRange = TPhysicsAssetEditorSelectionRange< UniqueIterator >;
const Selection& SelectedElements() const;
const Element& GetSelectedAt(const int32 InElementIndex) const;
const Element* GetSelectedAtValidIndex(const int32 InElementIndex) const;
bool IsValidIndex(const int32 InElementIndex) const;
bool ContainsType(const uint32 InElementTypeFlags) const;
int32 Num() const { return SelectedElementCollection.Num(); }
int32 NumOfType(const uint32 InElementTypeFlags) const;
void ClearSelection();
void ClearSelection(const uint32 InElementTypeFlags);
void ClearSelectionWithoutTransaction(const uint32 InElementTypeFlags); // This can be used to clear selected elements of type when inside an existing transaction.
Iterator SelectedElementsOfTypeIterator(const uint32 InElementTypeFlags) const { return Iterator(this, InElementTypeFlags); }
FilterRange SelectedElementsOfType(const uint32 InElementTypeFlags) const;
UniqueRange UniqueSelectedElementsOfType(const uint32 InElementTypeFlags) const;
bool ModifySelected(const TArray<Element>& InSelectedElements, const bool bSelected);
bool SetSelected(const TArray<Element>& InSelectedElements);
const Element* GetNextSelectedOfType(const int32 InElementIndex, const uint32 InElementTypeFlags) const;
const Element* GetLastSelectedOfType(const uint32 InElementTypeFlags) const;
private:
void ClearSelectionInternal();
void ClearSelectionInternal(const uint32 InElementTypeFlags, const bool bShouldCreateTransaction);
UPROPERTY()
TArray< FPhysicsAssetEditorSelectedElement > SelectedElementCollection;
};
// class TPhysicsAssetEditorUniqueIterator //
template< typename IteratorType > TPhysicsAssetEditorUniqueIterator< IteratorType >::TPhysicsAssetEditorUniqueIterator(Iterator InIterator)
: ManagedIterator(InIterator)
{}
template< typename IteratorType > bool TPhysicsAssetEditorUniqueIterator< IteratorType >::IsValid() const
{
return ManagedIterator.IsValid();
}
template< typename IteratorType > TPhysicsAssetEditorUniqueIterator< IteratorType >::operator bool() const
{
return ManagedIterator.IsValid();
}
template< typename IteratorType > const typename TPhysicsAssetEditorUniqueIterator< IteratorType >::Element& TPhysicsAssetEditorUniqueIterator< IteratorType >::operator*()
{
return ManagedIterator.operator*();
}
template< typename IteratorType > const typename TPhysicsAssetEditorUniqueIterator< IteratorType >::Element* TPhysicsAssetEditorUniqueIterator< IteratorType >::operator->()
{
return ManagedIterator.operator->();
}
template< typename IteratorType > void TPhysicsAssetEditorUniqueIterator< IteratorType >::operator++()
{
EncounteredIndexIntoParentSelection.Add(ManagedIterator.GetIndexIntoParentSelection());
while (IsValid() && EncounteredIndexIntoParentSelection.ContainsByPredicate([this](const int32& Element) { return ManagedIterator.GetParentSelection()->GetSelectedAt(Element).Index == ManagedIterator->Index; }))
{
++ManagedIterator;
}
}
template< typename IteratorType > void TPhysicsAssetEditorUniqueIterator< IteratorType >::operator--()
{
if (!EncounteredIndexIntoParentSelection.IsEmpty())
{
// Step back to the last encountered element index.
while (ManagedIterator.GetIndexIntoParentSelection() > EncounteredIndexIntoParentSelection.Last())
{
--ManagedIterator;
}
EncounteredIndexIntoParentSelection.Pop();
}
}
template< typename IteratorType > bool TPhysicsAssetEditorUniqueIterator< IteratorType >::operator==(const ThisType& Other) const
{
return (ManagedIterator == Other.ManagedIterator)
&& (EncounteredIndexIntoParentSelection == Other.EncounteredIndexIntoParentSelection);
}
// class TPhysicsAssetEditorSelectionRange //
template< typename IteratorType > TPhysicsAssetEditorSelectionRange< IteratorType >::TPhysicsAssetEditorSelectionRange(Iterator InBegin, Iterator InEnd)
: IteratorBegin(InBegin)
, IteratorEnd(InEnd)
{}
template< typename IteratorType > TPhysicsAssetEditorSelectionRange< IteratorType >::Iterator TPhysicsAssetEditorSelectionRange< IteratorType >::CreateConstIterator()
{
return begin();
}
template< typename IteratorType > TPhysicsAssetEditorSelectionRange< IteratorType >::Iterator TPhysicsAssetEditorSelectionRange< IteratorType >::begin() const
{
return IteratorBegin;
}
template< typename IteratorType > TPhysicsAssetEditorSelectionRange< IteratorType >::Iterator TPhysicsAssetEditorSelectionRange< IteratorType >::end() const
{
return IteratorEnd;
}
template< typename IteratorType > bool TPhysicsAssetEditorSelectionRange< IteratorType >::IsValid() const
{
return begin() != end();
}
template< typename IteratorType > TPhysicsAssetEditorSelectionRange< IteratorType >::operator bool() const
{
return IsValid();
}
template< typename IteratorType > bool TPhysicsAssetEditorSelectionRange< IteratorType >::IsEmpty() const
{
return !IsValid();
}
template< typename IteratorType > int32 TPhysicsAssetEditorSelectionRange< IteratorType >::Num() const
{
int32 Count = 0;
for (Iterator Itr = begin(); Itr != end(); ++Itr, ++Count);
return Count;
};
template< typename IteratorType > TArray< typename TPhysicsAssetEditorSelectionRange< IteratorType >::Element > TPhysicsAssetEditorSelectionRange< IteratorType >::ToArray()
{
TArray<Element> Array;
Algo::Copy(*this, Array);
return Array;
}
template< typename IteratorType > const typename TPhysicsAssetEditorSelectionRange< IteratorType >::Element& TPhysicsAssetEditorSelectionRange< IteratorType >::At(const int32 InIndex) const
{
Iterator Itr = begin();
for (int32 i = 0; i < InIndex; ++i, ++Itr);
return *Itr;
}