Files
UnrealEngine/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxCompareWindow.cpp
2025-05-18 13:04:45 +08:00

622 lines
20 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "FbxCompareWindow.h"
#include "Modules/ModuleManager.h"
#include "Widgets/Layout/SBorder.h"
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Layout/SBox.h"
#include "Widgets/Layout/SUniformGridPanel.h"
#include "Widgets/Layout/SScrollBox.h"
#include "Widgets/Layout/SSeparator.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Images/SImage.h"
#include "Widgets/Colors/SColorBlock.h"
#include "Widgets/Input/SCheckBox.h"
#include "Widgets/Views/SListView.h"
#include "Widgets/Views/STreeView.h"
#include "Widgets/Views/STableRow.h"
#include "Widgets/Layout/SSplitter.h"
#include "Styling/AppStyle.h"
#include "Factories/FbxAnimSequenceImportData.h"
#include "IDocumentation.h"
#include "PropertyEditorModule.h"
#include "IDetailsView.h"
#include "Framework/Commands/UIAction.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#include "Factories/FbxSceneImportFactory.h"
#include "Framework/Application/SlateApplication.h"
#include "Engine/SkeletalMesh.h"
#include "Engine/StaticMesh.h"
#include "Rendering/SkeletalMeshModel.h"
#include "Materials/Material.h"
#define LOCTEXT_NAMESPACE "FBXOption"
bool SFbxSkeltonConflictWindow::HasConflict()
{
if (SourceObject->IsA(USkeletalMesh::StaticClass()))
{
for (TSharedPtr<FSkeletonCompareData> SkeletonCompareData : DisplaySkeletonTreeItem)
{
if (SkeletonCompareData->bChildConflict)
{
//We have at least one skeleton conflict
return true;
}
}
}
return false;
}
void SFbxSkeltonConflictWindow::Construct(const FArguments& InArgs)
{
bRevertReimport = false;
bShowSectionFlag[EFBXCompareSection_Skeleton] = true;
bShowSectionFlag[EFBXCompareSection_References] = true;
WidgetWindow = InArgs._WidgetWindow;
if (InArgs._AssetReferencingSkeleton != nullptr)
{
//Copy the aray
AssetReferencingSkeleton = *(InArgs._AssetReferencingSkeleton);
}
SourceData = InArgs._SourceData;
ResultData = InArgs._ResultData;
SourceObject = InArgs._SourceObject;
bIsPreviewConflict = InArgs._bIsPreviewConflict;
if (SourceObject->IsA(USkeletalMesh::StaticClass()))
{
FilSkeletonTreeItem();
}
SetMatchJointInfo();
// Skeleton comparison
TSharedPtr<SWidget> SkeletonCompareSection = ConstructSkeletonComparison();
TSharedPtr<SWidget> SkeletonReferencesSection = ConstructSkeletonReference();
this->ChildSlot
[
SNew(SBox)
[
SNew(SVerticalBox)
+SVerticalBox::Slot()
.FillHeight(1.0f)
[
SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("ToolPanel.DarkGroupBorder"))
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.FillHeight(1.0f)
.Padding(2.0f)
[
SNew(SSplitter)
.Orientation(Orient_Vertical)
.ResizeMode(ESplitterResizeMode::Fill)
+ SSplitter::Slot()
.Value(0.8f)
[
// Skeleton Compare section
SkeletonCompareSection.ToSharedRef()
]
+ SSplitter::Slot()
.Value(0.2f)
[
// Skeleton Compare section
SkeletonReferencesSection.ToSharedRef()
]
]
]
]
+ SVerticalBox::Slot()
.AutoHeight()
.HAlign(HAlign_Right)
.Padding(2.0f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(2.0f, 0.0f)
[
SNew(SButton)
.HAlign(HAlign_Center)
.Text(LOCTEXT("SFbxSkeltonConflictWindow_Preview_Done", "Done"))
.OnClicked(this, &SFbxSkeltonConflictWindow::OnDone)
]
]
]
];
}
FReply SFbxSkeltonConflictWindow::SetSectionVisible(EFBXCompareSection SectionIndex)
{
bShowSectionFlag[SectionIndex] = !bShowSectionFlag[SectionIndex];
return FReply::Handled();
}
EVisibility SFbxSkeltonConflictWindow::IsSectionVisible(EFBXCompareSection SectionIndex)
{
return bShowSectionFlag[SectionIndex] ? EVisibility::Visible : EVisibility::Collapsed;
}
const FSlateBrush* SFbxSkeltonConflictWindow::GetCollapsableArrow(EFBXCompareSection SectionIndex) const
{
return bShowSectionFlag[SectionIndex] ? FAppStyle::GetBrush("Symbols.DownArrow") : FAppStyle::GetBrush("Symbols.RightArrow");
}
void RecursivelyExpandTreeItem(TSharedPtr<STreeView<TSharedPtr<FSkeletonCompareData>>> CompareTree, TSharedPtr<FSkeletonCompareData> RowData)
{
if (RowData->bInitialAutoExpand || !RowData->bMatchJoint || !RowData->bChildConflict)
{
return;
}
RowData->bInitialAutoExpand = true;
CompareTree->SetItemExpansion(RowData, true);
for (TSharedPtr<FSkeletonCompareData> ChildRowData : RowData->ChildJoints)
{
RecursivelyExpandTreeItem(CompareTree, ChildRowData);
}
}
TSharedPtr<SWidget> SFbxSkeltonConflictWindow::ConstructSkeletonComparison()
{
if (!SourceObject->IsA(USkeletalMesh::StaticClass()))
{
//Return an empty widget, we do not show the skeleton when the mesh is not a skeletal mesh
return SNew(SBox);
}
FText SkeletonStatus = bIsPreviewConflict ? FText(LOCTEXT("SFbxSkeltonConflictWindow_ConstructSkeletonComparison_MatchAndMergePreview", "The skeleton has some conflicts")) :
FText(ResultData->CompSkeleton.bSkeletonFitMesh ? LOCTEXT("SFbxSkeltonConflictWindow_ConstructSkeletonComparison_MatchAndMerge", "The skeleton can be merged") : LOCTEXT("SFbxSkeltonConflictWindow_ConstructSkeletonComparison_CannotMatchAndMerge", "The skeleton must be regenerated, it cannot be merged"));
CompareTree = SNew(STreeView< TSharedPtr<FSkeletonCompareData> >)
.SelectionMode(ESelectionMode::None)
.TreeItemsSource(&DisplaySkeletonTreeItem)
.OnGenerateRow(this, &SFbxSkeltonConflictWindow::OnGenerateRowCompareTreeView)
.OnGetChildren(this, &SFbxSkeltonConflictWindow::OnGetChildrenRowCompareTreeView);
for (TSharedPtr<FSkeletonCompareData> RowData : DisplaySkeletonTreeItem)
{
RecursivelyExpandTreeItem(CompareTree, RowData);
}
return SNew(SBox)
[
SNew(SBorder)
.Padding(FMargin(3))
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
[
SNew(SVerticalBox)
+SVerticalBox::Slot()
.AutoHeight()
.Padding(2)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(SButton)
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
.IsFocusable(false)
.ButtonStyle(FAppStyle::Get(), "NoBorder")
.OnClicked(this, &SFbxSkeltonConflictWindow::SetSectionVisible, EFBXCompareSection_Skeleton)
[
SNew(SImage).Image(this, &SFbxSkeltonConflictWindow::GetCollapsableArrow, EFBXCompareSection_Skeleton)
]
]
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(STextBlock)
.Font(FAppStyle::GetFontStyle("DetailsView.CategoryFontStyle"))
.Text(LOCTEXT("SFbxSkeltonConflictWindow_SkeletonCompareHeader", "Skeleton"))
]
]
+SVerticalBox::Slot()
.FillHeight(1.0f)
.Padding(2)
[
SNew(SBox)
.Visibility(TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &SFbxSkeltonConflictWindow::IsSectionVisible, EFBXCompareSection_Skeleton)))
[
SNew(SBorder)
.Padding(FMargin(3))
.BorderImage(FAppStyle::GetBrush("ToolPanel.DarkGroupBorder"))
[
SNew(SVerticalBox)
+SVerticalBox::Slot()
.AutoHeight()
.Padding(2)
[
SNew(STextBlock)
.Font(FAppStyle::GetFontStyle("DetailsView.CategoryFontStyle"))
.Text(SkeletonStatus)
.ColorAndOpacity(ResultData->CompSkeleton.bSkeletonFitMesh ? FSlateColor::UseForeground() : FSlateColor(FLinearColor(0.7f, 0.3f, 0.0f)))
]
+SVerticalBox::Slot()
.AutoHeight()
.Padding(2)
[
SNew(SSeparator)
.Orientation(EOrientation::Orient_Horizontal)
]
+SVerticalBox::Slot()
.FillHeight(1.0f)
.Padding(2)
[
CompareTree.ToSharedRef()
]
]
]
]
]
];
}
TSharedPtr<SWidget> SFbxSkeltonConflictWindow::ConstructSkeletonReference()
{
if (!SourceObject->IsA(USkeletalMesh::StaticClass()))
{
//Return an empty widget, we do not show the skeleton when the mesh is not a skeletal mesh
return SNew(SBox);
}
FString SkeletonReferenceStatistic;
if (AssetReferencingSkeleton.Num() > 0)
{
SkeletonReferenceStatistic += TEXT("Skeleton is references by ") + FString::FromInt(AssetReferencingSkeleton.Num()) + TEXT(" assets.");
}
return SNew(SBox)
[
SNew(SBorder)
.Padding(FMargin(3))
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
[
SNew(SVerticalBox)
+SVerticalBox::Slot()
.AutoHeight()
.Padding(2)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(SButton)
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
.IsFocusable(false)
.ButtonStyle(FAppStyle::Get(), "NoBorder")
.OnClicked(this, &SFbxSkeltonConflictWindow::SetSectionVisible, EFBXCompareSection_References)
[
SNew(SImage).Image(this, &SFbxSkeltonConflictWindow::GetCollapsableArrow, EFBXCompareSection_References)
]
]
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(STextBlock)
.Font(FAppStyle::GetFontStyle("DetailsView.CategoryFontStyle"))
.Text(LOCTEXT("SFbxSkeltonConflictWindow_SkeletonReferencesHeader", "References"))
]
]
+SVerticalBox::Slot()
.FillHeight(1.0f)
.Padding(2)
[
SNew(SBox)
.Visibility(TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &SFbxSkeltonConflictWindow::IsSectionVisible, EFBXCompareSection_References)))
[
SNew(SBorder)
.Padding(FMargin(3))
.BorderImage(FAppStyle::GetBrush("ToolPanel.DarkGroupBorder"))
[
SNew(SVerticalBox)
+SVerticalBox::Slot()
.AutoHeight()
.Padding(2)
[
SNew(STextBlock)
.Font(FAppStyle::GetFontStyle("DetailsView.CategoryFontStyle"))
.Text(FText::FromString(SkeletonReferenceStatistic))
]
+SVerticalBox::Slot()
.AutoHeight()
.Padding(2)
[
SNew(SSeparator)
.Orientation(EOrientation::Orient_Horizontal)
]
+SVerticalBox::Slot()
.FillHeight(1.0f)
.Padding(2)
[
//Show the asset referencing this skeleton
SNew(SListView<TSharedPtr<FString>>)
.ListItemsSource(&AssetReferencingSkeleton)
.OnGenerateRow(this, &SFbxSkeltonConflictWindow::OnGenerateRowAssetReferencingSkeleton)
]
]
]
]
]
];
}
class SCompareSkeletonTreeViewItem : public STableRow< TSharedPtr<FSkeletonCompareData> >
{
public:
SLATE_BEGIN_ARGS(SCompareSkeletonTreeViewItem)
: _SkeletonCompareData(nullptr)
, _SourceData(nullptr)
, _ResultData(nullptr)
{}
/** The item content. */
SLATE_ARGUMENT(TSharedPtr<FSkeletonCompareData>, SkeletonCompareData)
SLATE_ARGUMENT(FCompMesh*, SourceData)
SLATE_ARGUMENT(FCompMesh*, ResultData)
SLATE_END_ARGS()
/**
* Construct the widget
*
* @param InArgs A declaration from which to construct the widget
*/
void Construct(const FArguments& InArgs, const TSharedRef<STableViewBase>& InOwnerTableView)
{
SkeletonCompareData = InArgs._SkeletonCompareData;
SourceData = InArgs._SourceData;
ResultData = InArgs._ResultData;
//This is suppose to always be valid
check(SkeletonCompareData.IsValid());
check(SourceData != nullptr);
check(ResultData != nullptr);
const FSlateBrush* JointIcon = SkeletonCompareData->bMatchJoint ? FAppStyle::GetDefaultBrush() : SkeletonCompareData->FbxJointIndex != INDEX_NONE ? FAppStyle::GetBrush("FBXIcon.ReimportCompareAdd") : FAppStyle::GetBrush("FBXIcon.ReimportCompareRemoved");
//Prepare the tooltip
FString Tooltip = SkeletonCompareData->bMatchJoint ? TEXT("") : FText(SkeletonCompareData->FbxJointIndex != INDEX_NONE ? LOCTEXT("SCompareSkeletonTreeViewItem_AddJoint_tooltip", "Fbx reimport will add this joint") : LOCTEXT("SCompareSkeletonTreeViewItem_RemoveJoint_tooltip", "Fbx reimport will remove this joint")).ToString();
FSlateColor ForegroundTextColor = (SkeletonCompareData->bMatchJoint && !SkeletonCompareData->bChildConflict) ? FSlateColor::UseForeground() : (SkeletonCompareData->bMatchJoint ? FSlateColor(FLinearColor(0.9f, 0.7f, 0.5f)) : FSlateColor(FLinearColor(0.7f, 0.3f, 0.0f)));
this->ChildSlot
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(SExpanderArrow, SharedThis(this))
]
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(0.0f, 2.0f, 6.0f, 2.0f)
[
SNew(SImage)
.Image(JointIcon)
.Visibility(JointIcon != FAppStyle::GetDefaultBrush() ? EVisibility::Visible : EVisibility::Collapsed)
]
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
.Padding(0.0f, 3.0f, 6.0f, 3.0f)
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(FText::FromString(SkeletonCompareData->JointName.ToString()))
.ToolTipText(FText::FromString(Tooltip))
.ColorAndOpacity(ForegroundTextColor)
]
];
STableRow< TSharedPtr<FSkeletonCompareData> >::ConstructInternal(
STableRow::FArguments()
.ShowSelection(true),
InOwnerTableView
);
}
private:
/** The node info to build the tree view row from. */
TSharedPtr<FSkeletonCompareData> SkeletonCompareData;
FCompMesh *SourceData;
FCompMesh *ResultData;
};
TSharedRef<ITableRow> SFbxSkeltonConflictWindow::OnGenerateRowCompareTreeView(TSharedPtr<FSkeletonCompareData> RowData, const TSharedRef<STableViewBase>& Table)
{
TSharedRef< SCompareSkeletonTreeViewItem > ReturnRow = SNew(SCompareSkeletonTreeViewItem, Table)
.SkeletonCompareData(RowData)
.SourceData(SourceData)
.ResultData(ResultData);
return ReturnRow;
}
void SFbxSkeltonConflictWindow::OnGetChildrenRowCompareTreeView(TSharedPtr<FSkeletonCompareData> InParent, TArray< TSharedPtr<FSkeletonCompareData> >& OutChildren)
{
for (int32 ChildIndex = 0; ChildIndex < InParent->ChildJoints.Num(); ++ChildIndex)
{
TSharedPtr<FSkeletonCompareData> ChildJoint = InParent->ChildJoints[ChildIndex];
if (ChildJoint.IsValid())
{
OutChildren.Add(ChildJoint);
}
}
}
TSharedRef<ITableRow> SFbxSkeltonConflictWindow::OnGenerateRowAssetReferencingSkeleton(TSharedPtr<FString> InItem, const TSharedRef<STableViewBase>& OwnerTable)
{
int32 AssetListIndex = AssetReferencingSkeleton.Find(InItem);
bool LightBackgroundColor = AssetListIndex % 2 == 0;
return SNew(STableRow<TSharedPtr<FString> >, OwnerTable)
[
SNew(SBorder)
.BorderImage(LightBackgroundColor ? FAppStyle::GetBrush("ToolPanel.GroupBorder") : FAppStyle::GetBrush("ToolPanel.DarkGroupBorder"))
[
SNew(STextBlock)
.Text(FText::FromString(*(InItem.Get())))
]
];
}
void SFbxSkeltonConflictWindow::FilSkeletonTreeItem()
{
//Create all the entries
for (int32 RowIndex = 0; RowIndex < SourceData->CompSkeleton.Joints.Num(); ++RowIndex)
{
TSharedPtr<FSkeletonCompareData> CompareRowData = MakeShareable(new FSkeletonCompareData());
int32 AddedIndex = CurrentSkeletonTreeItem.Add(CompareRowData);
check(AddedIndex == RowIndex);
CompareRowData->CurrentJointIndex = RowIndex;
CompareRowData->JointName = SourceData->CompSkeleton.Joints[RowIndex].Name;
CompareRowData->ChildJointIndexes = SourceData->CompSkeleton.Joints[RowIndex].ChildIndexes;
}
//Set the childrens and parent pointer
for (int32 RowIndex = 0; RowIndex < SourceData->CompSkeleton.Joints.Num(); ++RowIndex)
{
check(CurrentSkeletonTreeItem.IsValidIndex(RowIndex));
TSharedPtr<FSkeletonCompareData> CompareRowData = CurrentSkeletonTreeItem[RowIndex];
if (CurrentSkeletonTreeItem.IsValidIndex(SourceData->CompSkeleton.Joints[RowIndex].ParentIndex))
{
CompareRowData->ParentJoint = CurrentSkeletonTreeItem[SourceData->CompSkeleton.Joints[RowIndex].ParentIndex];
}
for (int32 ChildJointIndex = 0; ChildJointIndex < CompareRowData->ChildJointIndexes.Num(); ++ChildJointIndex)
{
if (CurrentSkeletonTreeItem.IsValidIndex(CompareRowData->ChildJointIndexes[ChildJointIndex]))
{
CompareRowData->ChildJoints.Add(CurrentSkeletonTreeItem[CompareRowData->ChildJointIndexes[ChildJointIndex]]);
}
}
}
for (int32 RowIndex = 0; RowIndex < ResultData->CompSkeleton.Joints.Num(); ++RowIndex)
{
TSharedPtr<FSkeletonCompareData> CompareRowData = MakeShareable(new FSkeletonCompareData());
int32 AddedIndex = FbxSkeletonTreeItem.Add(CompareRowData);
check(AddedIndex == RowIndex);
CompareRowData->FbxJointIndex = RowIndex;
CompareRowData->JointName = ResultData->CompSkeleton.Joints[RowIndex].Name;
CompareRowData->ChildJointIndexes = ResultData->CompSkeleton.Joints[RowIndex].ChildIndexes;
}
//Set the childrens and parent pointer
for (int32 RowIndex = 0; RowIndex < ResultData->CompSkeleton.Joints.Num(); ++RowIndex)
{
check(FbxSkeletonTreeItem.IsValidIndex(RowIndex));
TSharedPtr<FSkeletonCompareData> CompareRowData = FbxSkeletonTreeItem[RowIndex];
if (FbxSkeletonTreeItem.IsValidIndex(ResultData->CompSkeleton.Joints[RowIndex].ParentIndex))
{
CompareRowData->ParentJoint = FbxSkeletonTreeItem[ResultData->CompSkeleton.Joints[RowIndex].ParentIndex];
}
for (int32 ChildJointIndex = 0; ChildJointIndex < CompareRowData->ChildJointIndexes.Num(); ++ChildJointIndex)
{
if (FbxSkeletonTreeItem.IsValidIndex(CompareRowData->ChildJointIndexes[ChildJointIndex]))
{
CompareRowData->ChildJoints.Add(FbxSkeletonTreeItem[CompareRowData->ChildJointIndexes[ChildJointIndex]]);
}
}
}
}
void SFbxSkeltonConflictWindow::RecursiveMatchJointInfo(TSharedPtr<FSkeletonCompareData> SkeletonItem)
{
TArray<TSharedPtr<FSkeletonCompareData>> DisplayChilds;
//Find the display child
if (CurrentSkeletonTreeItem.IsValidIndex(SkeletonItem->CurrentJointIndex))
{
for (int32 ChildIndex = 0; ChildIndex < CurrentSkeletonTreeItem[SkeletonItem->CurrentJointIndex]->ChildJoints.Num(); ++ChildIndex)
{
DisplayChilds.Add(CurrentSkeletonTreeItem[SkeletonItem->CurrentJointIndex]->ChildJoints[ChildIndex]);
}
}
if (FbxSkeletonTreeItem.IsValidIndex(SkeletonItem->FbxJointIndex))
{
for (int32 ChildIndex = 0; ChildIndex < FbxSkeletonTreeItem[SkeletonItem->FbxJointIndex]->ChildJoints.Num(); ++ChildIndex)
{
TSharedPtr<FSkeletonCompareData> FbxSkeletonItem = FbxSkeletonTreeItem[SkeletonItem->FbxJointIndex]->ChildJoints[ChildIndex];
bool bFoundChildMatch = false;
for (TSharedPtr<FSkeletonCompareData> DisplayChildJoint : DisplayChilds)
{
if (DisplayChildJoint->JointName == FbxSkeletonItem->JointName)
{
bFoundChildMatch = true;
DisplayChildJoint->bMatchJoint = true;
DisplayChildJoint->FbxJointIndex = FbxSkeletonItem->FbxJointIndex;
break;
}
}
if (!bFoundChildMatch)
{
DisplayChilds.Add(FbxSkeletonItem);
}
}
}
if (!SkeletonItem->bMatchJoint)
{
TSharedPtr<FSkeletonCompareData> ParentSkeletonItem = SkeletonItem->ParentJoint;
while (ParentSkeletonItem.IsValid() && ParentSkeletonItem->bChildConflict == false)
{
ParentSkeletonItem->bChildConflict = true;
ParentSkeletonItem = ParentSkeletonItem->ParentJoint;
}
}
//Set the new child list to the display joint
SkeletonItem->ChildJoints = DisplayChilds;
SkeletonItem->ChildJointIndexes.Empty();
for (TSharedPtr<FSkeletonCompareData> ChildJoint : SkeletonItem->ChildJoints)
{
ChildJoint->ParentJoint = SkeletonItem;
RecursiveMatchJointInfo(ChildJoint);
}
}
void SFbxSkeltonConflictWindow::SetMatchJointInfo()
{
TArray<TSharedPtr<FSkeletonCompareData>> RootJoint;
for (TSharedPtr<FSkeletonCompareData> CurrentSkeletonItem : CurrentSkeletonTreeItem)
{
if (!CurrentSkeletonItem->ParentJoint.IsValid())
{
DisplaySkeletonTreeItem.Add(CurrentSkeletonItem);
}
}
for (TSharedPtr<FSkeletonCompareData> CurrentSkeletonItem : FbxSkeletonTreeItem)
{
if (!CurrentSkeletonItem->ParentJoint.IsValid())
{
bool bInsertJoint = true;
for (TSharedPtr<FSkeletonCompareData> DisplayTreeItem : DisplaySkeletonTreeItem)
{
if(DisplayTreeItem->JointName == CurrentSkeletonItem->JointName)
{
DisplayTreeItem->FbxJointIndex = CurrentSkeletonItem->FbxJointIndex;
DisplayTreeItem->bMatchJoint = true;
bInsertJoint = false;
}
}
if (bInsertJoint)
{
DisplaySkeletonTreeItem.Add(CurrentSkeletonItem);
}
}
}
for (int32 SkeletonTreeIndex = 0; SkeletonTreeIndex < DisplaySkeletonTreeItem.Num(); ++SkeletonTreeIndex)
{
RecursiveMatchJointInfo(DisplaySkeletonTreeItem[SkeletonTreeIndex]);
}
}
#undef LOCTEXT_NAMESPACE