Skip to content

Commit

Permalink
Create prefabs and scenes during processing
Browse files Browse the repository at this point in the history
* Add PrefabHierarchyObject and SceneHierarchyObject
* Scene ordering remains the same, but prefabs get sorted by asset type
* This might solve an issue with pptr's inside a prefab. Previously, AssetsExportCollection.File was not changing while enumerating ExportableAssets.
* SceneExportCollection uses random export id's for artificially generated assets. Previously, there were no generated assets in scenes.
  • Loading branch information
ds5678 committed Feb 19, 2024
1 parent 05f503f commit 45cf0a3
Show file tree
Hide file tree
Showing 13 changed files with 388 additions and 226 deletions.
32 changes: 11 additions & 21 deletions Source/AssetRipper.Export.UnityProjects/Models/GlbModelExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
using AssetRipper.Assets.Export;
using AssetRipper.Assets.Generics;
using AssetRipper.Export.UnityProjects.Meshes;
using AssetRipper.Export.UnityProjects.Project;
using AssetRipper.Import.Logging;
using AssetRipper.Numerics;
using AssetRipper.Processing.Scenes;
using AssetRipper.Processing;
using AssetRipper.SourceGenerated.Classes.ClassID_1;
using AssetRipper.SourceGenerated.Classes.ClassID_137;
using AssetRipper.SourceGenerated.Classes.ClassID_18;
Expand All @@ -30,26 +29,17 @@ public partial class GlbModelExporter : BinaryAssetExporter
{
public override bool TryCreateCollection(IUnityObjectBase asset, [NotNullWhen(true)] out IExportCollection? exportCollection)
{
if (SceneHelpers.IsSceneCompatible(asset))
switch (asset.MainAsset)
{
if (asset.Collection.IsScene)
{
exportCollection = new GlbSceneModelExportCollection(this, asset.Collection.Scene);
}
else if (PrefabExportCollection.IsValidAsset(asset))
{
exportCollection = new GlbPrefabModelExportCollection(this, asset);
}
else
{
exportCollection = new FailExportCollection(this, asset);
}
return true;
}
else
{
exportCollection = null;
return false;
case SceneHierarchyObject sceneHierarchyObject:
exportCollection = new GlbSceneModelExportCollection(this, sceneHierarchyObject);
return true;
case PrefabHierarchyObject prefabHierarchyObject:
exportCollection = new GlbPrefabModelExportCollection(this, prefabHierarchyObject);
return true;
default:
exportCollection = null;
return false;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using AssetRipper.Assets;
using AssetRipper.Export.UnityProjects.Project;
using AssetRipper.Processing;

namespace AssetRipper.Export.UnityProjects.Models
{
public sealed class GlbPrefabModelExportCollection : PrefabExportCollection
{
public GlbPrefabModelExportCollection(GlbModelExporter assetExporter, IUnityObjectBase asset) : base(assetExporter, asset)
public GlbPrefabModelExportCollection(GlbModelExporter assetExporter, PrefabHierarchyObject asset) : base(assetExporter, asset)
{
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using AssetRipper.Assets.Collections;
using AssetRipper.Assets.Export;
using AssetRipper.Assets.Export;
using AssetRipper.Export.UnityProjects.Project;
using AssetRipper.Processing;

namespace AssetRipper.Export.UnityProjects.Models
{
public sealed class GlbSceneModelExportCollection : SceneExportCollection
{
public GlbSceneModelExportCollection(GlbModelExporter assetExporter, SceneDefinition scene) : base(assetExporter, scene)
public GlbSceneModelExportCollection(GlbModelExporter assetExporter, SceneHierarchyObject asset) : base(assetExporter, asset)
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ private bool ContainsID(long id)
}

public override AssetCollection File => m_file;
private AssetCollection m_file;
protected AssetCollection m_file;

/// <summary>
/// A one-to-one dictionary of export id's
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,87 +3,34 @@
using AssetRipper.Assets.Metadata;
using AssetRipper.IO.Files;
using AssetRipper.IO.Files.SerializedFiles;
using AssetRipper.Processing;
using AssetRipper.SourceGenerated;
using AssetRipper.SourceGenerated.Classes.ClassID_1;
using AssetRipper.SourceGenerated.Classes.ClassID_1001;
using AssetRipper.SourceGenerated.Classes.ClassID_18;
using AssetRipper.SourceGenerated.Classes.ClassID_2;
using AssetRipper.SourceGenerated.Classes.ClassID_468431735;
using AssetRipper.SourceGenerated.Extensions;
using AssetRipper.SourceGenerated.MarkerInterfaces;
using System.Diagnostics;

namespace AssetRipper.Export.UnityProjects.Project
{
public class PrefabExportCollection : AssetsExportCollection<IPrefabInstance>
{
public PrefabExportCollection(IAssetExporter assetExporter, IUnityObjectBase asset)
: this(assetExporter, GetRootGameObjectAndPrefab(asset))
public PrefabExportCollection(IAssetExporter assetExporter, PrefabHierarchyObject prefabHierarchyObject)
: base(assetExporter, prefabHierarchyObject.Prefab)
{
}

private PrefabExportCollection(IAssetExporter assetExporter, (IGameObject, IPrefabInstance) rootPrefabPair)
: base(assetExporter, rootPrefabPair.Item2)
{
(RootGameObject, Prefab) = rootPrefabPair;

foreach (IEditorExtension asset in RootGameObject.FetchHierarchy())
{
AddAsset(asset);
}
}

/// <summary>
/// <list>
/// <listheader>Valid Assets:</listheader>
/// <item>GameObject</item>
/// <item>Component attached to a GameObject</item>
/// <item>Prefab</item>
/// </list>
/// </summary>
/// <param name="asset">The asset being assessed.</param>
/// <returns>True if the asset can be used.</returns>
public static bool IsValidAsset(IUnityObjectBase asset)
{
return asset switch
{
IComponent component => component.GameObject_C2P is not null,
IGameObject => true,
IPrefabInstance => true,
_ => false,
};
RootGameObject = prefabHierarchyObject.Root;
Prefab = prefabHierarchyObject.Prefab;
Hierarchy = prefabHierarchyObject;
AddAssets(prefabHierarchyObject.Assets);
AddAsset(prefabHierarchyObject);
}

protected override string GetExportExtension(IUnityObjectBase asset) => PrefabKeyword;

private static (IGameObject, IPrefabInstance) GetRootGameObjectAndPrefab(IUnityObjectBase asset)
{
switch (asset)
{
case IGameObject gameObject:
{
IGameObject root = gameObject.GetRoot();
Debug.Assert(root.MainAsset is not null);
return (root, (IPrefabInstance)root.MainAsset);
}

case IComponent component:
{
IGameObject root = component.GameObject_C2P!.GetRoot();
Debug.Assert(root.MainAsset is not null);
return (root, (IPrefabInstance)root.MainAsset);
}

case IPrefabInstance prefab:
return (prefab.GetRootGameObject(), prefab);
default:
throw new NotSupportedException();
}
}

public override TransferInstructionFlags Flags => base.Flags | TransferInstructionFlags.SerializeForPrefabSystem;
public IGameObject RootGameObject { get; }
public IPrefabInstance Prefab { get; }
public PrefabHierarchyObject Hierarchy { get; }
/// <summary>
/// Prior to 2018.3, Prefab was an actual asset inside "*.prefab" files.
/// After that, PrefabImporter and PrefabInstance were introduced as a replacement.
Expand Down Expand Up @@ -114,12 +61,20 @@ public override IEnumerable<IUnityObjectBase> ExportableAssets
{
if (EmitPrefabAsset)
{
return Assets;
foreach (IUnityObjectBase asset in Hierarchy.Assets)
{
m_file = asset.Collection;
yield return asset;
}
}
else
{
Debug.Assert(Assets.First() is IPrefabInstanceMarker);
return Assets.Skip(1);//Skip the PrefabInstance asset
Debug.Assert(Hierarchy.Assets.Last() is IPrefabInstanceMarker);
foreach (IUnityObjectBase asset in Hierarchy.Assets.SkipLast(1))//Skip the PrefabInstance asset
{
m_file = asset.Collection;
yield return asset;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using AssetRipper.Assets.Metadata;
using AssetRipper.Import.Logging;
using AssetRipper.IO.Files;
using AssetRipper.Processing;
using AssetRipper.Processing.Scenes;
using AssetRipper.SourceGenerated.Classes.ClassID_1030;
using AssetRipper.SourceGenerated.Classes.ClassID_3;
Expand All @@ -12,23 +13,21 @@ namespace AssetRipper.Export.UnityProjects.Project
{
public class SceneExportCollection : ExportCollection, IComparer<IUnityObjectBase>
{
public SceneExportCollection(IAssetExporter assetExporter, SceneDefinition scene)
public SceneExportCollection(IAssetExporter assetExporter, SceneHierarchyObject hierarchy)
{
AssetExporter = assetExporter ?? throw new ArgumentNullException(nameof(assetExporter));
Scene = scene ?? throw new ArgumentNullException(nameof(scene));
CurrentFile = scene.Collections[0];//Have to set it to something.
ArgumentNullException.ThrowIfNull(assetExporter);
ArgumentNullException.ThrowIfNull(hierarchy);

List<IUnityObjectBase> components = new();
foreach (IUnityObjectBase asset in Scene.Collections.SelectMany(c => c))
AssetExporter = assetExporter;
Hierarchy = hierarchy;
CurrentFile = Hierarchy.Collection;//Have to set it to something.

foreach (IUnityObjectBase asset in Hierarchy.Assets)
{
if (SceneHelpers.IsSceneCompatible(asset))
{
components.Add(asset);
m_exportIDs.Add(asset.AssetInfo, asset.PathID);
}
m_exportIDs.Add(asset, asset.Collection is SerializedAssetCollection ? asset.PathID : ExportIdHandler.GetInternalId());
}
components.Sort(this);
componentArray = components.ToArray();

componentArray = hierarchy.Assets.Order(this).ToArray();
}

public override bool Export(IExportContainer container, string projectDirectory)
Expand Down Expand Up @@ -60,12 +59,12 @@ protected virtual bool ExportScene(IExportContainer container, string folderPath

public override bool Contains(IUnityObjectBase asset)
{
return m_exportIDs.ContainsKey(asset.AssetInfo);
return m_exportIDs.ContainsKey(asset);
}

public override long GetExportID(IExportContainer container, IUnityObjectBase asset)
{
return m_exportIDs[asset.AssetInfo];
return m_exportIDs[asset];
}

public override MetaPtr CreateExportPointer(IExportContainer container, IUnityObjectBase asset, bool isLocal)
Expand Down Expand Up @@ -110,6 +109,20 @@ public int Compare(IUnityObjectBase? obj1, IUnityObjectBase? obj2)
}

public override IEnumerable<IUnityObjectBase> Assets
{
get
{
foreach (IUnityObjectBase asset in Hierarchy.Assets)
{
CurrentFile = asset.Collection;
yield return asset;
}
CurrentFile = Hierarchy.Collection;
yield return Hierarchy;
}
}

public override IEnumerable<IUnityObjectBase> ExportableAssets
{
get
{
Expand All @@ -131,10 +144,11 @@ public override IEnumerable<IUnityObjectBase> Assets
public override AssetCollection File => CurrentFile;
public UnityGuid GUID => Scene.GUID;
public override IAssetExporter AssetExporter { get; }
public SceneDefinition Scene { get; }
public SceneHierarchyObject Hierarchy { get; }
public SceneDefinition Scene => Hierarchy.Scene;
private AssetCollection CurrentFile { get; set; }

private readonly IUnityObjectBase[] componentArray;
private readonly Dictionary<AssetInfo, long> m_exportIDs = new();
private readonly Dictionary<IUnityObjectBase, long> m_exportIDs = new();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using AssetRipper.Assets;
using AssetRipper.Processing;
using AssetRipper.Processing.Scenes;

namespace AssetRipper.Export.UnityProjects.Project
Expand All @@ -7,26 +8,17 @@ public class SceneYamlExporter : YamlExporterBase
{
public override bool TryCreateCollection(IUnityObjectBase asset, [NotNullWhen(true)] out IExportCollection? exportCollection)
{
if (SceneHelpers.IsSceneCompatible(asset))
switch (asset.MainAsset)
{
if (asset.Collection.IsScene)
{
exportCollection = new SceneExportCollection(this, asset.Collection.Scene);
}
else if (PrefabExportCollection.IsValidAsset(asset))
{
exportCollection = new PrefabExportCollection(this, asset);
}
else
{
exportCollection = new FailExportCollection(this, asset);
}
return true;
}
else
{
exportCollection = null;
return false;
case SceneHierarchyObject sceneHierarchyObject:
exportCollection = new SceneExportCollection(this, sceneHierarchyObject);
return true;
case PrefabHierarchyObject prefabHierarchyObject:
exportCollection = new PrefabExportCollection(this, prefabHierarchyObject);
return true;
default:
exportCollection = null;
return false;
}
}
}
Expand Down

0 comments on commit 45cf0a3

Please sign in to comment.