Skip to content

Instantly share code, notes, and snippets.

@Frooxius
Created June 7, 2018 09:10
Show Gist options
  • Save Frooxius/c923996857ecec936f3b27545efeb7f4 to your computer and use it in GitHub Desktop.
Save Frooxius/c923996857ecec936f3b27545efeb7f4 to your computer and use it in GitHub Desktop.
Asset Cleanup
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FrooxEngine
{
public static partial class WorldOptimizer
{
public static void CleanupAssets(World world)
{
var assets = world.RootSlot.Find("Assets");
if (assets == null)
return;
// cleanup the assets first
CleanupUnreferencedAssets(assets);
// cleanup leftover empty slots
CleanupSlotsWithNonpersistentComponents(assets, false);
}
public static void CleanupUnreferencedAssets(Slot root, bool ignoreNonpersistentUsers = true)
{
foreach (var assetProvider in root.GetComponentsInChildren<IAssetProvider>())
if (!IsReferencedOutsideHierarchy(assetProvider, root, ignoreNonpersistentUsers))
((Component)assetProvider).Persistent = false;
}
public static bool IsReferencedOutsideHierarchy(IAssetProvider assetProvider, Slot hierarchyRoot, bool ignoreNonpersistentUsers = true,
HashSet<IAssetProvider> walked = null)
{
if (walked == null)
walked = new HashSet<IAssetProvider>();
if (walked.Contains(assetProvider))
return false;
walked.Add(assetProvider);
foreach(var reference in assetProvider.References)
{
if (ignoreNonpersistentUsers && !reference.IsPersistent)
continue;
if (!reference.FindNearestParent<Slot>().IsChildOf(hierarchyRoot, true))
return true;
// check if the referencing component is also an asset provider, which might be on itself referenced outside
// the hiearchy
var referencingProvider = reference.FindNearestParent<Component>() as IAssetProvider;
if (referencingProvider != null)
if (IsReferencedOutsideHierarchy(referencingProvider, hierarchyRoot, ignoreNonpersistentUsers, walked))
return true;
}
// didn't find any reference outside the hierchy
return false;
}
public static void CleanupSlotsWithNonpersistentComponents(Slot root, bool includingSelf = true)
{
// run recursively on children first
for (int i = root.ChildrenCount-1; i >= 0; i--)
CleanupSlotsWithNonpersistentComponents(root[i]);
if(includingSelf)
{
if (root.Components.Count(c => c.Persistent) == 0 && root.Children.Count(ch => ch.PersistentSelf) == 0)
root.PersistentSelf = false;
}
}
public static void CleanupEmptySlots(Slot root, bool includingSelf = true)
{
// run it recursively on children first
for(int i = root.ChildrenCount-1; i >= 0; i--)
CleanupEmptySlots(root[i]);
// the current slot has no componets and children, delete it
if(includingSelf)
{
if (root.ComponentCount == 0 && root.ChildrenCount == 0)
root.Destroy();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment