// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. #include "StructViewerNode.h" #include "AssetData.h" #include "PropertyHandle.h" #include "Misc/ScopedSlowTask.h" #include "Engine/UserDefinedStruct.h" #define LOCTEXT_NAMESPACE "StructViewer" FStructViewerNodeData::FStructViewerNodeData() : StructName(TEXT("None")) , StructDisplayName(LOCTEXT("None", "None")) { } FStructViewerNodeData::FStructViewerNodeData(const UScriptStruct* InStruct) : StructName(InStruct->GetName()) , StructDisplayName(InStruct->GetDisplayNameText()) , StructPath(*InStruct->GetPathName()) , Struct(InStruct) { if (const UScriptStruct* ParentStruct = Cast(InStruct->GetSuperStruct())) { ParentStructPath = *ParentStruct->GetPathName(); } } FStructViewerNodeData::FStructViewerNodeData(const FAssetData& InStructAsset) : StructName(InStructAsset.AssetName.ToString()) , StructPath(InStructAsset.ObjectPath) { // Attempt to find the struct asset in the case where it's already been loaded Struct = FindObject(nullptr, *StructPath.ToString()); // Cache the resolved display name if available, or synthesize one if the struct asset is unloaded StructDisplayName = Struct.IsValid() ? Struct->GetDisplayNameText() : FText::AsCultureInvariant(FName::NameToDisplayString(StructName, false)); } const UScriptStruct* FStructViewerNodeData::GetStruct() const { return Struct.Get(); } const UUserDefinedStruct* FStructViewerNodeData::GetStructAsset() const { return Cast(Struct.Get()); } bool FStructViewerNodeData::LoadStruct() const { if (Struct.IsValid()) { return true; } // Attempt to load the struct if (!StructPath.IsNone()) { FScopedSlowTask SlowTask(0.0f, LOCTEXT("LoadingStruct", "Loading Struct...")); SlowTask.MakeDialogDelayed(1.0f); Struct = LoadObject(nullptr, *StructPath.ToString()); } // Re-cache the resolved display name as it may be different than the one we synthesized for an unloaded struct asset if (Struct.IsValid()) { StructDisplayName = Struct->GetDisplayNameText(); return true; } return false; } void FStructViewerNodeData::AddChild(const TSharedRef& InChild) { InChild->ParentNode = AsShared(); ChildNodes.Add(InChild); } void FStructViewerNodeData::AddUniqueChild(const TSharedRef& InChild) { const bool bAlreadyAChild = ChildNodes.ContainsByPredicate([&InChild](const TSharedPtr& InExistingChild) -> bool { return InExistingChild->GetStructPath() == InChild->GetStructPath(); }); if (!bAlreadyAChild) { AddChild(InChild); } } bool FStructViewerNodeData::RemoveChild(const FName InStructPath) { for (auto ChildIt = ChildNodes.CreateIterator(); ChildIt; ++ChildIt) { if ((*ChildIt)->GetStructPath() == InStructPath) { ChildIt.RemoveCurrent(); return true; } } return false; } FStructViewerNode::FStructViewerNode() : NodeData(MakeShared()) , bPassedFilter(true) { } FStructViewerNode::FStructViewerNode(const TSharedRef& InData, const TSharedPtr& InPropertyHandle, const bool InPassedFilter) : NodeData(InData) , PropertyHandle(InPropertyHandle) , bPassedFilter(InPassedFilter) { } FText FStructViewerNode::GetStructDisplayName(const EStructViewerNameTypeToDisplay InNameType) const { switch (InNameType) { case EStructViewerNameTypeToDisplay::StructName: return FText::AsCultureInvariant(GetStructName()); case EStructViewerNameTypeToDisplay::DisplayName: return GetStructDisplayName(); case EStructViewerNameTypeToDisplay::Dynamic: { const FText BasicName = FText::AsCultureInvariant(GetStructName()); const FText DisplayName = GetStructDisplayName(); const FString SynthesizedDisplayName = FName::NameToDisplayString(BasicName.ToString(), false); // Only show both names if we have a display name set that is different from the basic name and not synthesized from it return (DisplayName.IsEmpty() || DisplayName.ToString().Equals(BasicName.ToString()) || DisplayName.ToString().Equals(SynthesizedDisplayName)) ? BasicName : FText::Format(LOCTEXT("StructDynamicDisplayNameFmt", "{0} ({1})"), BasicName, DisplayName); } default: break; } ensureMsgf(false, TEXT("FStructViewerNode::GetStructName called with invalid name type.")); return GetStructDisplayName(); } void FStructViewerNode::AddChild(const TSharedRef& InChild) { InChild->ParentNode = AsShared(); ChildNodes.Add(InChild); } void FStructViewerNode::AddUniqueChild(const TSharedRef& InChild) { const bool bAlreadyAChild = ChildNodes.ContainsByPredicate([&InChild](const TSharedPtr& InExistingChild) -> bool { return InExistingChild->GetStructPath() == InChild->GetStructPath(); }); if (!bAlreadyAChild) { AddChild(InChild); } } void FStructViewerNode::SortChildrenRecursive() { SortChildren(); for (const TSharedPtr& ChildNode : ChildNodes) { ChildNode->SortChildrenRecursive(); } } void FStructViewerNode::SortChildren() { ChildNodes.Sort(&SortPredicate); } bool FStructViewerNode::SortPredicate(const TSharedPtr& InA, const TSharedPtr& InB) { check(InA.IsValid()); check(InB.IsValid()); const FString& AString = InA->GetStructName(); const FString& BString = InB->GetStructName(); return AString < BString; } bool FStructViewerNode::IsRestricted() const { return PropertyHandle && PropertyHandle->IsRestricted(GetStructName()); } #undef LOCTEXT_NAMESPACE