2021-04-29 19:32:06 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "ContentBrowserVirtualPathTree.h"
|
|
|
|
|
#include "IContentBrowserDataModule.h"
|
|
|
|
|
#include "ContentBrowserDataSubsystem.h"
|
|
|
|
|
#include "Misc/StringBuilder.h"
|
|
|
|
|
#include "Settings/ContentBrowserSettings.h"
|
|
|
|
|
|
|
|
|
|
FContentBrowserVirtualPathTree::FContentBrowserVirtualPathTree()
|
|
|
|
|
{
|
|
|
|
|
ClassesPrefix = TEXT("Classes_");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FContentBrowserVirtualPathTree::Reset()
|
|
|
|
|
{
|
|
|
|
|
VirtualToInternalMounts.Reset();
|
|
|
|
|
ParentPathToChildPaths.Reset();
|
|
|
|
|
ChildPathToParentPath.Reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FStringView FContentBrowserVirtualPathTree::GetMountPointFromPath(const FStringView InPath, bool& bOutHadClassesPrefix)
|
|
|
|
|
{
|
|
|
|
|
FStringView MountPointStringView;
|
|
|
|
|
|
|
|
|
|
int32 SecondForwardSlash = INDEX_NONE;
|
|
|
|
|
if (FStringView(InPath.GetData() + 1, InPath.Len() - 1).FindChar(TEXT('/'), SecondForwardSlash))
|
|
|
|
|
{
|
|
|
|
|
MountPointStringView = FStringView(InPath.GetData() + 1, SecondForwardSlash);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
MountPointStringView = FStringView(InPath.GetData() + 1, InPath.Len() - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FString ClassesPrefix = TEXT("Classes_");
|
|
|
|
|
if (MountPointStringView.StartsWith(ClassesPrefix))
|
|
|
|
|
{
|
|
|
|
|
MountPointStringView.RightInline(MountPointStringView.Len() - ClassesPrefix.Len());
|
|
|
|
|
bOutHadClassesPrefix = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
bOutHadClassesPrefix = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return MountPointStringView;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FContentBrowserVirtualPathTree::CachePath(FName Path, FName InternalPath, TFunctionRef<void(FName)> OnPathAdded)
|
|
|
|
|
{
|
|
|
|
|
if (Path.IsNone())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ParentPathToChildPaths.Contains(Path))
|
|
|
|
|
{
|
|
|
|
|
// Already cached - nothing more to do
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FString PathStr = Path.ToString();
|
|
|
|
|
check(PathStr.Len() >= 2); // Must be at least "/A"
|
|
|
|
|
check(PathStr[0] == '/'); // Must start with a "/"
|
|
|
|
|
|
|
|
|
|
// Paths are cached without their trailing slash, so if the given path has a trailing slash, test it again now as it may already be cached
|
|
|
|
|
if (PathStr[PathStr.Len() - 1] == '/')
|
|
|
|
|
{
|
|
|
|
|
PathStr.RemoveAt(PathStr.Len() - 1, 1, /*bAllowShrinking*/false);
|
|
|
|
|
Path = *PathStr;
|
|
|
|
|
|
|
|
|
|
if (ParentPathToChildPaths.Contains(Path))
|
|
|
|
|
{
|
|
|
|
|
// Already cached - nothing more to do
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FName LastPath;
|
|
|
|
|
|
|
|
|
|
// Ensure an entry for the root of the path
|
|
|
|
|
{
|
|
|
|
|
static const FName PathRoot = "/";
|
|
|
|
|
|
|
|
|
|
if (!ParentPathToChildPaths.Contains(PathRoot))
|
|
|
|
|
{
|
|
|
|
|
ParentPathToChildPaths.Add(PathRoot);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LastPath = PathRoot;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Walk each part of the path, adding known path entries if required
|
|
|
|
|
// This manipulates PathStr in-place to avoid making any string copies
|
|
|
|
|
TCHAR* PathCharPtr = &PathStr[1]; // Skip over the first / when scanning
|
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
const TCHAR PathChar = *PathCharPtr;
|
|
|
|
|
if (PathChar == '/' || PathChar == 0)
|
|
|
|
|
{
|
|
|
|
|
// We've found a path separator (or the end of the string), so process this part of the path
|
|
|
|
|
(*PathCharPtr) = 0; // Null terminate this part of the string so we can create an FName from it
|
|
|
|
|
const FName CurrentPath = *PathStr;
|
|
|
|
|
(*PathCharPtr) = PathChar; // Restore the original character now
|
|
|
|
|
|
|
|
|
|
check(!CurrentPath.IsNone()); // Path parts cannot be empty
|
|
|
|
|
check(*(PathCharPtr-1) != '/'); // The previous character cannot be a /, as that would suggest a malformed path such as "/Game//MyAsset"
|
|
|
|
|
|
|
|
|
|
bool bAddedPath = false;
|
|
|
|
|
if (!ParentPathToChildPaths.Contains(CurrentPath))
|
|
|
|
|
{
|
|
|
|
|
ParentPathToChildPaths.Add(CurrentPath);
|
|
|
|
|
bAddedPath = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!LastPath.IsNone())
|
|
|
|
|
{
|
|
|
|
|
// Add us as a known child of our parent path
|
|
|
|
|
TSet<FName>& ChildPaths = ParentPathToChildPaths.FindChecked(LastPath);
|
|
|
|
|
ChildPaths.Add(CurrentPath);
|
|
|
|
|
|
|
|
|
|
// Make sure we know how to find our parent again later on
|
|
|
|
|
ChildPathToParentPath.Add(CurrentPath, LastPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bAddedPath)
|
|
|
|
|
{
|
|
|
|
|
OnPathAdded(CurrentPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LastPath = CurrentPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (PathChar == 0)
|
|
|
|
|
{
|
|
|
|
|
// End of the string
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++PathCharPtr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VirtualToInternalMounts.Add(Path, InternalPath);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FContentBrowserVirtualPathTree::RemovePath(FName Path, TFunctionRef<void(FName)> OnPathRemoved)
|
|
|
|
|
{
|
|
|
|
|
if (Path.IsNone())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ParentPathToChildPaths.Contains(Path))
|
|
|
|
|
{
|
|
|
|
|
// Paths are cached without their trailing slash, so if the given path has a trailing slash, test it again now as it may already be cached
|
|
|
|
|
// We do this after the initial map test as: a) Most paths are well formed, b) This avoids string allocations until we know we need them
|
|
|
|
|
FString PathStr = Path.ToString();
|
|
|
|
|
if (PathStr[PathStr.Len() - 1] == '/')
|
|
|
|
|
{
|
|
|
|
|
PathStr.RemoveAt(PathStr.Len() - 1, 1, /*bAllowShrinking*/false);
|
|
|
|
|
Path = *PathStr;
|
|
|
|
|
|
|
|
|
|
if (!ParentPathToChildPaths.Contains(Path))
|
|
|
|
|
{
|
|
|
|
|
// Doesn't exist - nothing more to do
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Doesn't exist - nothing more to do
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We also need to gather up and remove any children of this path
|
|
|
|
|
TSet<FName> SubPathsToRemove;
|
|
|
|
|
GetSubPaths(Path, SubPathsToRemove, /*bRecurse=*/true);
|
|
|
|
|
|
|
|
|
|
// Sort the sub-paths by length, longest -> shortest, so that children are notified before their parents
|
|
|
|
|
SubPathsToRemove.Sort([](FName SubPathOne, FName SubPathTwo)
|
|
|
|
|
{
|
|
|
|
|
return SubPathOne.Compare(SubPathTwo) > 0;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Simply remove sub-paths from both maps
|
|
|
|
|
for (const FName& SubPathToRemove : SubPathsToRemove)
|
|
|
|
|
{
|
|
|
|
|
ParentPathToChildPaths.Remove(SubPathToRemove);
|
|
|
|
|
ChildPathToParentPath.Remove(SubPathToRemove);
|
|
|
|
|
OnPathRemoved(SubPathToRemove);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We also need to remove ourself from our parent list before removing ourself from the maps
|
|
|
|
|
{
|
|
|
|
|
const FName* ParentPathPtr = ChildPathToParentPath.Find(Path);
|
|
|
|
|
if (ParentPathPtr)
|
|
|
|
|
{
|
|
|
|
|
TSet<FName>& ChildPaths = ParentPathToChildPaths.FindChecked(*ParentPathPtr);
|
|
|
|
|
ChildPaths.Remove(Path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VirtualToInternalMounts.Remove(Path);
|
|
|
|
|
ParentPathToChildPaths.Remove(Path);
|
|
|
|
|
ChildPathToParentPath.Remove(Path);
|
|
|
|
|
OnPathRemoved(Path);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FContentBrowserVirtualPathTree::PathExists(FName Path, bool& bIsFullyVirtual) const
|
|
|
|
|
{
|
|
|
|
|
if (Path.IsNone())
|
|
|
|
|
{
|
|
|
|
|
bIsFullyVirtual = false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const TSet<FName>* ChildPathsPtr = ParentPathToChildPaths.Find(Path);
|
|
|
|
|
if (!ChildPathsPtr)
|
|
|
|
|
{
|
|
|
|
|
// Paths are cached without their trailing slash, so if the given path has a trailing slash, test it again now as it may already be cached
|
|
|
|
|
// We do this after the initial map test as: a) Most paths are well formed, b) This avoids string allocations until we know we need them
|
|
|
|
|
FString PathStr = Path.ToString();
|
|
|
|
|
if (PathStr[PathStr.Len() - 1] == '/')
|
|
|
|
|
{
|
|
|
|
|
PathStr.RemoveAt(PathStr.Len() - 1, 1, /*bAllowShrinking*/false);
|
|
|
|
|
Path = *PathStr;
|
|
|
|
|
|
|
|
|
|
ChildPathsPtr = ParentPathToChildPaths.Find(Path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bIsFullyVirtual = ChildPathsPtr && ChildPathsPtr->Num() > 0;
|
|
|
|
|
|
|
|
|
|
return ChildPathsPtr != nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FContentBrowserVirtualPathTree::GetAllPaths(TSet<FName>& OutPaths) const
|
|
|
|
|
{
|
|
|
|
|
OutPaths.Reset();
|
|
|
|
|
EnumerateAllPaths([&OutPaths](FName Path)
|
|
|
|
|
{
|
|
|
|
|
OutPaths.Emplace(Path);
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
return OutPaths.Num() > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FContentBrowserVirtualPathTree::EnumerateAllPaths(TFunctionRef<bool(FName)> Callback) const
|
|
|
|
|
{
|
|
|
|
|
for (const auto& PathPair : ParentPathToChildPaths)
|
|
|
|
|
{
|
|
|
|
|
if (!Callback(PathPair.Key))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FContentBrowserVirtualPathTree::GetSubPaths(FName BasePath, TSet<FName>& OutPaths, bool bRecurse) const
|
|
|
|
|
{
|
|
|
|
|
const int32 OutPathsOriginalNum = OutPaths.Num();
|
|
|
|
|
return EnumerateSubPaths(BasePath, [&OutPaths](FName Path, FName InternalPath)
|
|
|
|
|
{
|
|
|
|
|
OutPaths.Emplace(Path);
|
|
|
|
|
return true;
|
|
|
|
|
}, bRecurse) && OutPaths.Num() > OutPathsOriginalNum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FContentBrowserVirtualPathTree::EnumerateSubPaths(FName BasePath, TFunctionRef<bool(FName, FName)> Callback, bool bRecurse) const
|
|
|
|
|
{
|
|
|
|
|
if (BasePath.IsNone())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const TSet<FName>* ChildPathsPtr = ParentPathToChildPaths.Find(BasePath);
|
|
|
|
|
if (!ChildPathsPtr)
|
|
|
|
|
{
|
|
|
|
|
// Paths are cached without their trailing slash, so if the given path has a trailing slash, test it again now as it may already be cached
|
|
|
|
|
// We do this after the initial map test as: a) Most paths are well formed, b) This avoids string allocations until we know we need them
|
|
|
|
|
FString BasePathStr = BasePath.ToString();
|
|
|
|
|
if (BasePathStr[BasePathStr.Len() - 1] == '/')
|
|
|
|
|
{
|
|
|
|
|
BasePathStr.RemoveAt(BasePathStr.Len() - 1, 1, /*bAllowShrinking*/false);
|
|
|
|
|
BasePath = *BasePathStr;
|
|
|
|
|
|
|
|
|
|
ChildPathsPtr = ParentPathToChildPaths.Find(BasePath);
|
|
|
|
|
if (!ChildPathsPtr)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const FName& ChildPath : *ChildPathsPtr)
|
|
|
|
|
{
|
|
|
|
|
check(ParentPathToChildPaths.Contains(ChildPath)); // This failing is an integrity violation as this entry lists a child that we don't know about
|
|
|
|
|
|
|
|
|
|
const FName* InternalPath = VirtualToInternalMounts.Find(ChildPath);
|
|
|
|
|
if (!Callback(ChildPath, InternalPath ? *InternalPath : NAME_None))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bRecurse)
|
|
|
|
|
{
|
|
|
|
|
EnumerateSubPaths(ChildPath, Callback, /*bRecurse=*/true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FName FContentBrowserVirtualPathTree::GetParentPath(FName Path) const
|
|
|
|
|
{
|
|
|
|
|
if (Path.IsNone())
|
|
|
|
|
{
|
|
|
|
|
return NAME_None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const FName* ParentPathPtr = ChildPathToParentPath.Find(Path))
|
|
|
|
|
{
|
|
|
|
|
return *ParentPathPtr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NAME_None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32 FContentBrowserVirtualPathTree::NumPaths() const
|
|
|
|
|
{
|
|
|
|
|
return ParentPathToChildPaths.Num();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FContentBrowserVirtualPathTree::IsShowAllFolderEnabled() const
|
|
|
|
|
{
|
|
|
|
|
return GetDefault<UContentBrowserSettings>()->bShowAllFolder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FString& FContentBrowserVirtualPathTree::GetAllFolderPrefix() const
|
|
|
|
|
{
|
|
|
|
|
if (UContentBrowserDataSubsystem* ContentBrowserDataSubsystem = IContentBrowserDataModule::Get().GetSubsystem())
|
|
|
|
|
{
|
|
|
|
|
return ContentBrowserDataSubsystem->GetAllFolderPrefix();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FString EmptyString;
|
|
|
|
|
return EmptyString;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-11 01:10:20 -04:00
|
|
|
EContentBrowserPathType FContentBrowserVirtualPathTree::TryConvertVirtualPathToInternal(FStringView InPath, FStringBuilderBase& OutPath) const
|
2021-04-29 19:32:06 -04:00
|
|
|
{
|
2021-05-11 01:10:20 -04:00
|
|
|
OutPath.Reset();
|
|
|
|
|
|
2021-04-29 19:32:06 -04:00
|
|
|
// Special case
|
2021-05-11 01:10:20 -04:00
|
|
|
static const FStringView RootPath(TEXT("/"));
|
|
|
|
|
if (InPath.Equals(RootPath))
|
2021-04-29 19:32:06 -04:00
|
|
|
{
|
2021-05-11 01:10:20 -04:00
|
|
|
OutPath.Append(InPath);
|
2021-04-29 19:32:06 -04:00
|
|
|
return EContentBrowserPathType::Virtual;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-11 01:10:20 -04:00
|
|
|
if (InPath.Len() == 0)
|
2021-04-29 19:32:06 -04:00
|
|
|
{
|
|
|
|
|
return EContentBrowserPathType::None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Walk path until reaches internal mount point or ends remaining as a virtual path
|
|
|
|
|
bool bReachedMountPoint = false;
|
|
|
|
|
bool bFailedPathExists = false;
|
|
|
|
|
int32 SplitIndex = 0;
|
2021-05-11 01:10:20 -04:00
|
|
|
const TCHAR* PathStr = InPath.GetData();
|
|
|
|
|
const TCHAR* PathStrEnd = PathStr + InPath.Len();
|
2021-04-29 19:32:06 -04:00
|
|
|
const TCHAR* PathCharPtr = PathStr + 1;
|
|
|
|
|
for (;;)
|
|
|
|
|
{
|
2021-05-11 01:10:20 -04:00
|
|
|
if (PathCharPtr >= PathStrEnd || *PathCharPtr == TEXT('/'))
|
2021-04-29 19:32:06 -04:00
|
|
|
{
|
|
|
|
|
const FName CheckPath(PathCharPtr - PathStr, PathStr);
|
|
|
|
|
bool bCheckPathIsFullyVirtual = false;
|
|
|
|
|
if (PathExists(CheckPath, bCheckPathIsFullyVirtual))
|
|
|
|
|
{
|
|
|
|
|
if (!bCheckPathIsFullyVirtual)
|
|
|
|
|
{
|
|
|
|
|
bReachedMountPoint = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SplitIndex = (int32)(PathCharPtr - PathStr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
bFailedPathExists = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-11 01:10:20 -04:00
|
|
|
if (PathCharPtr >= PathStrEnd)
|
2021-04-29 19:32:06 -04:00
|
|
|
{
|
|
|
|
|
// End of the string
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++PathCharPtr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (SplitIndex > 0)
|
|
|
|
|
{
|
|
|
|
|
if (!bReachedMountPoint)
|
|
|
|
|
{
|
|
|
|
|
if (bFailedPathExists)
|
|
|
|
|
{
|
|
|
|
|
return EContentBrowserPathType::None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Strip "/All" to turn fully virtual path into something that can survive being saved/loaded to .ini file for favorites, colors and other systems
|
|
|
|
|
if (IsShowAllFolderEnabled())
|
|
|
|
|
{
|
2021-05-11 01:10:20 -04:00
|
|
|
FStringView InvariantPathView(InPath);
|
2021-04-29 19:32:06 -04:00
|
|
|
InvariantPathView.RightChopInline(GetAllFolderPrefix().Len());
|
|
|
|
|
if (InvariantPathView.Len() == 0)
|
|
|
|
|
{
|
2021-05-11 01:10:20 -04:00
|
|
|
OutPath.Append(TEXT("/"));
|
2021-04-29 19:32:06 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-05-11 01:10:20 -04:00
|
|
|
OutPath.Append(InvariantPathView);
|
2021-04-29 19:32:06 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-05-11 01:10:20 -04:00
|
|
|
OutPath.Append(InPath);
|
2021-04-29 19:32:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return EContentBrowserPathType::Virtual;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-11 01:10:20 -04:00
|
|
|
FStringView InternalPathView(InPath);
|
2021-04-29 19:32:06 -04:00
|
|
|
InternalPathView.RightChopInline(SplitIndex);
|
2021-05-11 01:10:20 -04:00
|
|
|
OutPath.Append(InternalPathView);
|
2021-04-29 19:32:06 -04:00
|
|
|
return EContentBrowserPathType::Internal;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (bReachedMountPoint)
|
|
|
|
|
{
|
2021-05-11 01:10:20 -04:00
|
|
|
OutPath.Append(InPath);
|
2021-04-29 19:32:06 -04:00
|
|
|
return EContentBrowserPathType::Internal;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return EContentBrowserPathType::None;
|
|
|
|
|
}
|
2021-05-11 01:10:20 -04:00
|
|
|
|
|
|
|
|
EContentBrowserPathType FContentBrowserVirtualPathTree::TryConvertVirtualPathToInternal(FStringView InPath, FString& OutPath) const
|
|
|
|
|
{
|
|
|
|
|
FNameBuilder OutPathBuilder;
|
|
|
|
|
const EContentBrowserPathType ConvertedType = TryConvertVirtualPathToInternal(InPath, OutPathBuilder);
|
|
|
|
|
OutPath = FString(FStringView(OutPathBuilder));
|
|
|
|
|
return ConvertedType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EContentBrowserPathType FContentBrowserVirtualPathTree::TryConvertVirtualPathToInternal(FName InPath, FName& OutPath) const
|
|
|
|
|
{
|
|
|
|
|
FNameBuilder OutPathBuilder;
|
|
|
|
|
const EContentBrowserPathType ConvertedType = TryConvertVirtualPathToInternal(FNameBuilder(InPath), OutPathBuilder);
|
|
|
|
|
OutPath = FName(FStringView(OutPathBuilder));
|
|
|
|
|
return ConvertedType;
|
|
|
|
|
}
|