Files
UnrealEngine/Engine/Plugins/Experimental/Animation/HierarchyTable/Source/Runtime/Private/HierarchyTable.cpp
2025-05-18 13:04:45 +08:00

222 lines
4.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "HierarchyTable.h"
#include "Animation/Skeleton.h"
#include "ReferenceSkeleton.h"
UHierarchyTable::UHierarchyTable()
{
}
bool FHierarchyTableEntryData::HasOverriddenChildren() const
{
return IsOverriddenOrHasOverriddenChildren(false);
}
bool FHierarchyTableEntryData::IsOverriddenOrHasOverriddenChildren(const bool bIncludeSelf) const
{
if (bIncludeSelf && IsOverridden())
{
return true;
}
TArray<const FHierarchyTableEntryData*> Children = OwnerTable->GetChildren(*this);
for (const FHierarchyTableEntryData* Child : Children)
{
if (Child->IsOverriddenOrHasOverriddenChildren(true))
{
return true;
}
}
return false;
}
void FHierarchyTableEntryData::ToggleOverridden()
{
if (Payload.IsSet())
{
Payload.Reset();
}
else
{
Payload = *GetFromClosestAncestor();
}
}
const TOptional<FInstancedStruct>& FHierarchyTableEntryData::GetPayload() const
{
return Payload;
}
const FInstancedStruct* FHierarchyTableEntryData::GetActualValue() const
{
return IsOverridden() ? Payload.GetPtrOrNull() : GetFromClosestAncestor();
}
const FHierarchyTableEntryData* FHierarchyTableEntryData::GetClosestAncestor() const
{
return IsOverridden() ? this : OwnerTable->GetTableEntry(Parent)->GetClosestAncestor();
}
const FInstancedStruct* FHierarchyTableEntryData::GetFromClosestAncestor() const
{
check(Parent != INDEX_NONE);
const FHierarchyTableEntryData* const ParentEntry = OwnerTable->GetTableEntry(Parent);
return ParentEntry->GetActualValue();
}
TArray<const FHierarchyTableEntryData*> UHierarchyTable::GetChildren(const FHierarchyTableEntryData& Parent) const
{
int32 ParentIndex = TableData.IndexOfByPredicate([Parent](const FHierarchyTableEntryData& Candidate)
{
return Candidate.Identifier == Parent.Identifier;
});
if (ParentIndex == INDEX_NONE)
{
return TArray<const FHierarchyTableEntryData*>();
}
TArray<const FHierarchyTableEntryData*> Children;
for (const FHierarchyTableEntryData& Entry : TableData)
{
if (Entry.Parent == ParentIndex)
{
Children.Add(&Entry);
}
}
return Children;
}
bool UHierarchyTable::HasIdentifier(const FName Identifier) const
{
return TableData.ContainsByPredicate([Identifier](const FHierarchyTableEntryData& Entry)
{
return Entry.Identifier == Identifier;
});
}
int32 UHierarchyTable::AddEntry(const FHierarchyTableEntryData& Entry)
{
// Do not allow entries with duplicate identifiers
if (HasIdentifier(Entry.Identifier))
{
return INDEX_NONE;
}
const int32 EntryIndex = TableData.Add(Entry);
RegenerateHierarchyGuid();
return EntryIndex;
}
void UHierarchyTable::AddBulkEntries(const TConstArrayView<FHierarchyTableEntryData> Entries)
{
for (const FHierarchyTableEntryData& Entry : Entries)
{
if (!HasIdentifier(Entry.Identifier))
{
TableData.Add(Entry);
}
}
RegenerateHierarchyGuid();
}
void UHierarchyTable::RemoveEntry(const int32 IndexToRemove)
{
if (!TableData.IsValidIndex(IndexToRemove))
{
return;
}
FHierarchyTableEntryData& EntryToRemove = TableData[IndexToRemove];
for (int32 EntryIndex = 0; EntryIndex < TableData.Num(); ++EntryIndex)
{
FHierarchyTableEntryData& Entry = TableData[EntryIndex];
if (Entry.Parent == IndexToRemove)
{
Entry.Parent = EntryToRemove.Parent;
}
else if (Entry.Parent > IndexToRemove)
{
--Entry.Parent;
}
}
TableData.RemoveAt(IndexToRemove);
RegenerateHierarchyGuid();
}
FInstancedStruct UHierarchyTable::CreateDefaultValue() const
{
FInstancedStruct OutStruct;
OutStruct.InitializeAs(ElementType);
return OutStruct;
}
const FHierarchyTableEntryData* const UHierarchyTable::GetTableEntry(const FName EntryIdentifier) const
{
for (const FHierarchyTableEntryData& Entry : TableData)
{
if (Entry.Identifier == EntryIdentifier)
{
return &Entry;
}
}
return nullptr;
}
const FHierarchyTableEntryData* const UHierarchyTable::GetTableEntry(const int32 EntryIndex) const
{
if (TableData.IsValidIndex(EntryIndex))
{
return &TableData[EntryIndex];
}
return nullptr;
}
FHierarchyTableEntryData* const UHierarchyTable::GetMutableTableEntry(const int32 EntryIndex)
{
if (TableData.IsValidIndex(EntryIndex))
{
return &TableData[EntryIndex];
}
return nullptr;
}
void UHierarchyTable::EmptyTable()
{
TableData.Empty();
RegenerateHierarchyGuid();
}
FGuid UHierarchyTable::GetHierarchyGuid()
{
return HierarchyGuid;
}
void UHierarchyTable::RegenerateHierarchyGuid()
{
HierarchyGuid = FGuid::NewGuid();
}
int32 UHierarchyTable::GetTableEntryIndex(const FName EntryIdentifier) const
{
for (int32 EntryIndex = 0; EntryIndex < TableData.Num(); ++EntryIndex)
{
if (TableData[EntryIndex].Identifier == EntryIdentifier)
{
return EntryIndex;
}
}
return INDEX_NONE;
}