bool UWorldComposition::UpdateEditorStreamingState(const FVector& InLocation) { UWorld* OwningWorld = GetWorld(); bool bStateChanged = false; // Handle only editor worlds if (!OwningWorld->IsGameWorld() && !OwningWorld->IsVisibilityRequestPending()) { // Get the list of visible and hidden levels from current view point TArray<FDistanceVisibleLevel> DistanceVisibleLevels; TArray<FDistanceVisibleLevel> DistanceHiddenLevels; GetDistanceVisibleLevels(InLocation, DistanceVisibleLevels, DistanceHiddenLevels); // Hidden levels for (const auto& Level : DistanceHiddenLevels) { ULevelStreaming* EditorStreamingLevel = OwningWorld->GetLevelStreamingForPackageName(TilesStreaming[Level.TileIdx]->GetWorldAssetPackageFName()); if (EditorStreamingLevel && EditorStreamingLevel->IsLevelLoaded() && EditorStreamingLevel->bShouldBeVisibleInEditor != false) { EditorStreamingLevel->bShouldBeVisibleInEditor = false; bStateChanged = true; } } // Visible levels for (const auto& Level : DistanceVisibleLevels) { ULevelStreaming* EditorStreamingLevel = OwningWorld->GetLevelStreamingForPackageName(TilesStreaming[Level.TileIdx]->GetWorldAssetPackageFName()); if (EditorStreamingLevel && EditorStreamingLevel->IsLevelLoaded() && EditorStreamingLevel->bShouldBeVisibleInEditor != true) { EditorStreamingLevel->bShouldBeVisibleInEditor = true; bStateChanged = true; } } } return bStateChanged; }
void FFoliageInstanceBaseCache::CompactInstanceBaseCache(AInstancedFoliageActor* IFA) { UWorld* World = IFA->GetWorld(); if (!World || World->IsGameWorld()) { return; } FFoliageInstanceBaseCache& Cache = IFA->InstanceBaseCache; TSet<FFoliageInstanceBaseId> BasesInUse; for (auto& Pair : IFA->FoliageMeshes) { for (const auto& Pair : Pair.Value->ComponentHash) { if (Pair.Key != FFoliageInstanceBaseCache::InvalidBaseId) { BasesInUse.Add(Pair.Key); } } } // Look for any removed maps TSet<FFoliageInstanceBasePtr> InvalidBasePtrs; for (auto& Pair : Cache.InstanceBaseLevelMap) { const auto& WorldAsset = Pair.Key; bool bExists = (WorldAsset == World); // Check sub-levels if (!bExists) { const FName PackageName = FName(*FPackageName::ObjectPathToPackageName(WorldAsset.ToStringReference().ToString())); if (World->WorldComposition) { bExists = World->WorldComposition->DoesTileExists(PackageName); } else { bExists = (World->GetLevelStreamingForPackageName(PackageName) != nullptr); } } if (!bExists) { InvalidBasePtrs.Append(Pair.Value); Cache.InstanceBaseLevelMap.Remove(Pair.Key); } else { // Remove dead links for (int32 i = Pair.Value.Num()-1; i >= 0; --i) { // Base needs to be removed if it's not in use by existing instances or component was removed if (Pair.Value[i].IsNull() || !BasesInUse.Contains(Cache.GetInstanceBaseId(Pair.Value[i]))) { InvalidBasePtrs.Add(Pair.Value[i]); Pair.Value.RemoveAt(i); } } if (Pair.Value.Num() == 0) { Cache.InstanceBaseLevelMap.Remove(Pair.Key); } } } TSet<FFoliageInstanceBaseId> InvalidBaseIds; Cache.InstanceBaseInvMap.Empty(); // Look for any removed base components for (const auto& Pair : Cache.InstanceBaseMap) { const FFoliageInstanceBaseInfo& BaseInfo = Pair.Value; if (InvalidBasePtrs.Contains(BaseInfo.BasePtr)) { InvalidBaseIds.Add(Pair.Key); Cache.InstanceBaseMap.Remove(Pair.Key); } else { // Regenerate inverse map check(!Cache.InstanceBaseInvMap.Contains(BaseInfo.BasePtr)); Cache.InstanceBaseInvMap.Add(BaseInfo.BasePtr, Pair.Key); } } if (InvalidBaseIds.Num()) { for (auto& Pair : IFA->FoliageMeshes) { auto& MeshInfo = Pair.Value; MeshInfo->ComponentHash.Empty(); int32 InstanceIdx = 0; for (FFoliageInstance& Instance : MeshInfo->Instances) { if (InvalidBaseIds.Contains(Instance.BaseId)) { Instance.BaseId = FFoliageInstanceBaseCache::InvalidBaseId; } MeshInfo->ComponentHash.FindOrAdd(Instance.BaseId).Add(InstanceIdx); InstanceIdx++; } } Cache.InstanceBaseMap.Compact(); Cache.InstanceBaseLevelMap.Compact(); } }