// Copyright Epic Games, Inc. All Rights Reserved. #include "ActorFolderHierarchy.h" #include "Engine/Level.h" #include "ISceneOutlinerMode.h" #include "WorldTreeItem.h" #include "LevelTreeItem.h" #include "ActorTreeItem.h" #include "ActorFolderTreeItem.h" #include "EditorActorFolders.h" #include "EditorFolderUtils.h" #include "ActorMode.h" #include "LevelInstance/LevelInstanceInterface.h" FActorFolderHierarchy::FActorFolderHierarchy(ISceneOutlinerMode* InMode, const TWeakObjectPtr& World, const FFolder::FRootObject& InRootObject) : ISceneOutlinerHierarchy(InMode) , RepresentingWorld(World) , RootObject(InRootObject) { // ActorFolderHierarchy should only be used with a mode which is showing folders check(Mode->ShouldShowFolders()); } FSceneOutlinerTreeItemPtr FActorFolderHierarchy::FindOrCreateParentItem(const ISceneOutlinerTreeItem& Item, const TMap& Items, bool bCreate) { if (Item.IsA()) { return nullptr; } else if (const FActorFolderTreeItem* ActorFolderItem = Item.CastTo()) { const FFolder ParentPath = ActorFolderItem->GetFolder().GetParent(); // If the folder has no parent path if (ParentPath.IsNone()) { if (UObject* Object = ParentPath.GetRootObjectPtr()) { if (const FSceneOutlinerTreeItemPtr* ParentItem = Items.Find(Object)) { return *ParentItem; } else if (bCreate) { FFolder Folder = ActorFolderItem->GetFolder(); if (Folder.GetRootObject() == RootObject) { // If item belongs to a LevelInstance if (ILevelInstanceInterface* RootLevelInstance = Cast(Folder.GetRootObjectPtr())) { return Mode->CreateItemFor(CastChecked(RootLevelInstance), true); } } } } else { if (const FSceneOutlinerTreeItemPtr* ParentItem = Items.Find(ActorFolderItem->World.Get())) { return *ParentItem; } else if (bCreate) { // Parent World UWorld* OwningWorld = ActorFolderItem->World.Get(); check(OwningWorld); return Mode->CreateItemFor(OwningWorld, true); } } } else if (const FSceneOutlinerTreeItemPtr* ParentItem = Items.Find(ParentPath)) { return *ParentItem; } else if(bCreate) { return Mode->CreateItemFor(FActorFolderTreeItem(ParentPath, ActorFolderItem->World), true); } } return nullptr; } void FActorFolderHierarchy::CreateWorldChildren(UWorld* World, TArray& OutItems) const { FActorFolders::Get().ForEachFolderWithRootObject(*World, RootObject, [this, World, &OutItems](const FFolder& Folder) { if (FSceneOutlinerTreeItemPtr FolderItem = Mode->CreateItemFor(FActorFolderTreeItem(Folder, World))) { OutItems.Add(FolderItem); } return true; }); if (FFolder::IsRootObjectValid(RootObject)) { UObject* RootObjectPtr = FFolder::GetRootObjectPtr(RootObject); if (ILevelInstanceInterface* RootLevelInstance = Cast(RootObjectPtr)) { if (FSceneOutlinerTreeItemPtr ActorItem = Mode->CreateItemFor(CastChecked(RootLevelInstance), true)) { OutItems.Add(ActorItem); } } else if (ULevel* RootLevel = Cast(RootObjectPtr)) { if (FActorMode::IsActorLevelDisplayable(RootLevel)) { if (FSceneOutlinerTreeItemPtr ActorItem = Mode->CreateItemFor(RootLevel, true)) { OutItems.Add(ActorItem); } } } } } void FActorFolderHierarchy::CreateItems(TArray& OutItems) const { check(RepresentingWorld.IsValid()); if (FFolder::IsRootObjectPersistentLevel(RootObject)) { if (FSceneOutlinerTreeItemPtr WorldItem = Mode->CreateItemFor(RepresentingWorld.Get())) { OutItems.Add(WorldItem); } } CreateWorldChildren(RepresentingWorld.Get(), OutItems); } void FActorFolderHierarchy::CreateChildren(const FSceneOutlinerTreeItemPtr& Item, TArray& OutChildren) const { auto CreateChildrenFolders = [this](UWorld* InWorld, const FFolder& InParentFolder, const FFolder::FRootObject& InFolderRootObject, TArray& OutChildren) { FActorFolders::Get().ForEachFolderWithRootObject(*InWorld, InFolderRootObject, [this, InWorld, &InParentFolder, &OutChildren](const FFolder& Folder) { if (Folder.IsChildOf(InParentFolder)) { if (FSceneOutlinerTreeItemPtr NewFolderItem = Mode->CreateItemFor(FActorFolderTreeItem(Folder, InWorld))) { OutChildren.Add(NewFolderItem); } } return true; }); }; UWorld* World = RepresentingWorld.Get(); if (const FWorldTreeItem* WorldItem = Item->CastTo()) { check(WorldItem->World == RepresentingWorld); CreateWorldChildren(WorldItem->World.Get(), OutChildren); } else if (FActorTreeItem* ParentActorItem = Item->CastTo()) { AActor* ParentActor = ParentActorItem->Actor.Get(); if (const ILevelInstanceInterface* LevelInstanceParent = Cast(ParentActor)) { check(ParentActor->GetWorld() == World); FFolder ParentFolder = ParentActor->GetFolder(); CreateChildrenFolders(World, ParentFolder, ParentActor, OutChildren); } } else if (FActorFolderTreeItem* FolderItem = Item->CastTo()) { check(FolderItem->World.Get() == World); FFolder ParentFolder = FolderItem->GetFolder(); check(!ParentFolder.IsNone()); CreateChildrenFolders(World, ParentFolder, ParentFolder.GetRootObject(), OutChildren); } }