diff --git a/Source/AssetRipper.Export.UnityProjects/ExportHandler.cs b/Source/AssetRipper.Export.UnityProjects/ExportHandler.cs index 8c3c9b669..2effed853 100644 --- a/Source/AssetRipper.Export.UnityProjects/ExportHandler.cs +++ b/Source/AssetRipper.Export.UnityProjects/ExportHandler.cs @@ -12,11 +12,10 @@ using AssetRipper.Processing.AnimatorControllers; using AssetRipper.Processing.Assemblies; using AssetRipper.Processing.AudioMixers; using AssetRipper.Processing.Editor; -using AssetRipper.Processing.ScriptableObject; -using AssetRipper.Processing.PrefabOutlining; -using AssetRipper.Processing.Scenes; -using AssetRipper.Processing.Textures; using AssetRipper.Processing.Prefabs; +using AssetRipper.Processing.Scenes; +using AssetRipper.Processing.ScriptableObject; +using AssetRipper.Processing.Textures; namespace AssetRipper.Export.UnityProjects; @@ -68,10 +67,6 @@ public class ExportHandler yield return new AudioMixerProcessor(); yield return new EditorFormatProcessor(Settings.ProcessingSettings.BundledAssetsExportMode); //Static mesh separation goes here - if (Settings.ProcessingSettings.EnablePrefabOutlining) - { - yield return new PrefabOutliningProcessor(); - } yield return new LightingDataProcessor();//Needs to be after static mesh separation yield return new PrefabProcessor(); yield return new SpriteProcessor(); diff --git a/Source/AssetRipper.Processing/PrefabOutlining/GameObjectCloner.cs b/Source/AssetRipper.Processing/PrefabOutlining/GameObjectCloner.cs deleted file mode 100644 index 12672fc07..000000000 --- a/Source/AssetRipper.Processing/PrefabOutlining/GameObjectCloner.cs +++ /dev/null @@ -1,59 +0,0 @@ -using AssetRipper.Assets; -using AssetRipper.Assets.Cloning; -using AssetRipper.Assets.Collections; -using AssetRipper.SourceGenerated; -using AssetRipper.SourceGenerated.Classes.ClassID_1; -using AssetRipper.SourceGenerated.Extensions; - -namespace AssetRipper.Processing.PrefabOutlining; - -public static class GameObjectCloner -{ - public static IGameObject Clone(IGameObject source, ProcessedAssetCollection processedCollection) - { - Dictionary clonedAssetDictionary = []; - foreach (IUnityObjectBase asset in source.FetchHierarchy()) - { - IUnityObjectBase clonedAsset = processedCollection.CreateAsset(asset.ClassID, AssetFactory.Create); - clonedAssetDictionary.Add(asset, clonedAsset); - } - ClonedAssetResolver resolver = new ClonedAssetResolver(clonedAssetDictionary); - foreach ((IUnityObjectBase asset, IUnityObjectBase clonedAsset) in clonedAssetDictionary) - { - PPtrConverter converter = new PPtrConverter(asset.Collection, clonedAsset.Collection, resolver); - clonedAsset.CopyValues(asset, converter); - } - return (IGameObject)clonedAssetDictionary[source]; - } - - private sealed class ClonedAssetResolver : IAssetResolver - { - private readonly Dictionary cache; - - public ClonedAssetResolver(Dictionary cache) - { - this.cache = cache; - } - - public T? Resolve(IUnityObjectBase? asset) where T : IUnityObjectBase - { - if (asset is null) - { - return default; - } - else if (cache.TryGetValue(asset, out IUnityObjectBase? clonedAsset)) - { - return TryCast(clonedAsset); - } - else - { - return TryCast(asset); - } - } - - private static T? TryCast(IUnityObjectBase asset) where T : IUnityObjectBase - { - return asset is T t ? t : default; - } - } -} diff --git a/Source/AssetRipper.Processing/PrefabOutlining/GameObjectInfo.cs b/Source/AssetRipper.Processing/PrefabOutlining/GameObjectInfo.cs deleted file mode 100644 index 793851238..000000000 --- a/Source/AssetRipper.Processing/PrefabOutlining/GameObjectInfo.cs +++ /dev/null @@ -1,172 +0,0 @@ -using AssetRipper.Assets.Collections; -using AssetRipper.Assets.Generics; -using AssetRipper.SourceGenerated.Classes.ClassID_1; -using AssetRipper.SourceGenerated.Classes.ClassID_2; -using AssetRipper.SourceGenerated.Classes.ClassID_4; -using AssetRipper.SourceGenerated.Extensions; -using AssetRipper.SourceGenerated.Subclasses.PPtr_Component; -using AssetRipper.SourceGenerated.Subclasses.PPtr_Transform; - -namespace AssetRipper.Processing.PrefabOutlining; - -internal readonly struct GameObjectInfo : IEquatable -{ - public GameObjectInfo(GameObjectInfo?[] children, int[] components) - { - Children = children; - Components = components; - Hash = CalculateHash(children, components); - } - - private GameObjectInfo?[] Children { get; } - private int[] Components { get; } - private int Hash { get; } - - public override string ToString() - { - return $"Children: {Children.Length} Components: {Components.Length}"; - } - - public override bool Equals(object? obj) - { - return obj is GameObjectInfo info && Equals(info); - } - - public bool Equals(GameObjectInfo other) - { - return Hash == other.Hash - && Components.AsSpan().SequenceEqual(other.Components.AsSpan()) - && Children.AsSpan().SequenceEqual(other.Children.AsSpan()); - } - - public override int GetHashCode() => Hash; - - public static bool operator ==(GameObjectInfo left, GameObjectInfo right) - { - return left.Equals(right); - } - - public static bool operator !=(GameObjectInfo left, GameObjectInfo right) - { - return !(left == right); - } - - private static int CalculateHash(GameObjectInfo?[] children, int[] components) - { - HashCode hashCode = new(); - for (int i = 0; i < components.Length; i++) - { - hashCode.Add(components[i]); - } - for (int i = 0; i < children.Length; i++) - { - hashCode.Add(children[i]); - } - return hashCode.ToHashCode(); - } - - public static GameObjectInfo FromGameObject(IGameObject root) - { - GetTransformAndComponentArray(root, out ITransform? transform, out int[] components); - - GameObjectInfo?[] children; - if (transform is null) - { - children = []; - } - else - { - PPtrAccessList childList = transform.Children_C4P; - if (childList.Count == 0) - { - children = []; - } - else - { - children = new GameObjectInfo?[childList.Count]; - for (int i = 0; i < childList.Count; i++) - { - IGameObject? child = childList[i]?.GameObject_C4P; - children[i] = child is null ? null : FromGameObject(child); - } - } - } - - return new GameObjectInfo(children, components); - } - - public static void AddCollectionToDictionary(AssetCollection collection, Dictionary dictionary) - { - foreach (IGameObject gameObject in collection.OfType()) - { - AddHierarchyToDictionary(gameObject, dictionary); - } - } - - public static GameObjectInfo AddHierarchyToDictionary(IGameObject root, Dictionary dictionary) - { - if (dictionary.TryGetValue(root, out GameObjectInfo info)) - { - return info; - } - - GetTransformAndComponentArray(root, out ITransform? transform, out int[] components); - - GameObjectInfo?[] children; - if (transform is null) - { - children = []; - } - else - { - PPtrAccessList childList = transform.Children_C4P; - if (childList.Count == 0) - { - children = []; - } - else - { - children = new GameObjectInfo?[childList.Count]; - for (int i = 0; i < childList.Count; i++) - { - IGameObject? child = childList[i]?.GameObject_C4P; - children[i] = child is null ? null : AddHierarchyToDictionary(child, dictionary); - } - } - } - - info = new GameObjectInfo(children, components); - dictionary.Add(root, info); - return info; - } - - private static void GetTransformAndComponentArray(IGameObject root, out ITransform? transform, out int[] components) - { - transform = null; - PPtrAccessList componentList = root.GetComponentAccessList(); - if (componentList.Count == 0) - { - components = []; - } - else - { - components = new int[componentList.Count]; - for (int i = 0; i < componentList.Count; i++) - { - IComponent? component = componentList[i]; - if (component is not null) - { - components[i] = component.ClassID; - if (component is ITransform t) - { - transform = t; - } - } - else - { - components[i] = -1; - } - } - } - } -} diff --git a/Source/AssetRipper.Processing/PrefabOutlining/PrefabOutliningProcessor.cs b/Source/AssetRipper.Processing/PrefabOutlining/PrefabOutliningProcessor.cs deleted file mode 100644 index a8fee4dca..000000000 --- a/Source/AssetRipper.Processing/PrefabOutlining/PrefabOutliningProcessor.cs +++ /dev/null @@ -1,138 +0,0 @@ -using AssetRipper.Assets.Bundles; -using AssetRipper.Assets.Collections; -using AssetRipper.Import.Logging; -using AssetRipper.SourceGenerated; -using AssetRipper.SourceGenerated.Classes.ClassID_1; -using AssetRipper.SourceGenerated.Classes.ClassID_4; -using AssetRipper.SourceGenerated.Extensions; - -namespace AssetRipper.Processing.PrefabOutlining; - -public sealed class PrefabOutliningProcessor : IAssetProcessor -{ - //Documentation note: prefab variants were introduced in 2018.3. - //That does not affect this processor currently, but it may have an impact on future improvements. - //https://blog.unity.com/technology/introducing-unity-2018-3 - - public void Process(GameData gameData) - { - Logger.Info(LogCategory.Processing, "Prefab Outlining"); - ProcessedAssetCollection processedCollection = gameData.AddNewProcessedCollection("Outlined Prefabs"); - MakeDictionaries( - gameData.GameBundle, - out Dictionary infoDictionary, - out Dictionary sceneInfo); - MakeBoxes( - infoDictionary, - sceneInfo, - out Dictionary>> boxes, - out HashSet prefabRoots); - foreach ((string name, Dictionary> variants) in boxes) - { - if (variants.Count != 1) - { - continue;//We want the simplest implementation to start out - } - - (_, List box) = variants.First(); - - if (box.Any(g => prefabRoots.Contains(g))) - { - continue;//Prefab already exists - } - - Logger.Info(LogCategory.Processing, $"Recreating prefab for {name}"); - - AddCopyToCollection(name, box[0], processedCollection); - } - } - - private static void AddCopyToCollection(string name, IGameObject source, ProcessedAssetCollection collection) - { - //AddPrefabPlaceHolder(name, collection); - AddNewPrefab(name, source, collection); - } - - private static void AddNewPrefab(string name, IGameObject source, ProcessedAssetCollection collection) - { - IGameObject root = GameObjectCloner.Clone(source, collection); - root.Name = name; - root.SetIsActive(true); - - ITransform transform = root.GetTransform(); - transform.LocalPosition_C4.Reset(); - transform.LocalRotation_C4.Reset(); - transform.LocalScale_C4.SetValues(1, 1, 1); - transform.LocalEulerAnglesHint_C4?.Reset(); - transform.RootOrder_C4 = 0; - transform.Father_C4.Reset(); - } - - private static void AddPrefabPlaceHolder(string name, ProcessedAssetCollection collection) - { - //Place holder code until source gen improves - - IGameObject root = CreateNewGameObject(collection); - root.Name = name; - root.SetIsActive(true); - root.TagString = TagManagerConstants.UntaggedTag; - - ITransform rootTransform = CreateNewTransform(collection); - rootTransform.GameObject_C4P = root; - rootTransform.RootOrder_C4 = 0; - //Since this Transform has no Father, its RootOrder is zero. - - root.AddComponent(ClassIDType.Transform, rootTransform); - - IGameObject child = CreateNewGameObject(collection); - child.Name = "This prefab is a placeholder until AssetRipper improves."; - child.SetIsActive(true); - child.TagString = TagManagerConstants.UntaggedTag; - - ITransform childTransform = CreateNewTransform(collection); - childTransform.GameObject_C4P = child; - childTransform.RootOrder_C4 = 0; - //Since this Transform is the only child, its RootOrder is zero. - - childTransform.Father_C4P = rootTransform; - rootTransform.Children_C4P.Add(childTransform); - - child.AddComponent(ClassIDType.Transform, childTransform); - } - - private static IGameObject CreateNewGameObject(ProcessedAssetCollection collection) - { - return collection.CreateAsset((int)ClassIDType.GameObject, GameObject.Create); - } - - private static ITransform CreateNewTransform(ProcessedAssetCollection collection) - { - return collection.CreateAsset((int)ClassIDType.Transform, Transform.Create); - } - - private static void MakeBoxes(Dictionary infoDictionary, Dictionary sceneInfo, out Dictionary>> boxes, out HashSet prefabRoots) - { - boxes = []; - prefabRoots = []; - foreach ((IGameObject gameObject, GameObjectInfo info) in infoDictionary) - { - string name = GameObjectNameCleaner.CleanName(gameObject.Name); - boxes.GetOrAdd(name).GetOrAdd(info).Add(gameObject); - if (!sceneInfo[gameObject.Collection] && gameObject.IsRoot()) - { - prefabRoots.Add(gameObject); - } - } - } - - private static void MakeDictionaries(GameBundle gameBundle, out Dictionary infoDictionary, out Dictionary sceneInfo) - { - infoDictionary = []; - sceneInfo = []; - foreach (AssetCollection collection in gameBundle.FetchAssetCollections()) - { - sceneInfo.Add(collection, collection.IsScene); - GameObjectInfo.AddCollectionToDictionary(collection, infoDictionary); - } - } -}