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();
	}
}