ScriptableObject grouping for PostProcessProfile

This commit is contained in:
ds5678 2025-02-05 17:18:58 -08:00
parent 54664db447
commit 481a067bb2
6 changed files with 68 additions and 24 deletions

View File

@ -12,7 +12,7 @@ using AssetRipper.Processing.AnimatorControllers;
using AssetRipper.Processing.Assemblies; using AssetRipper.Processing.Assemblies;
using AssetRipper.Processing.AudioMixers; using AssetRipper.Processing.AudioMixers;
using AssetRipper.Processing.Editor; using AssetRipper.Processing.Editor;
using AssetRipper.Processing.Playable; using AssetRipper.Processing.ScriptableObject;
using AssetRipper.Processing.PrefabOutlining; using AssetRipper.Processing.PrefabOutlining;
using AssetRipper.Processing.Scenes; using AssetRipper.Processing.Scenes;
using AssetRipper.Processing.Textures; using AssetRipper.Processing.Textures;
@ -75,7 +75,7 @@ public class ExportHandler
yield return new LightingDataProcessor();//Needs to be after static mesh separation yield return new LightingDataProcessor();//Needs to be after static mesh separation
yield return new PrefabProcessor(); yield return new PrefabProcessor();
yield return new SpriteProcessor(); yield return new SpriteProcessor();
yield return new PlayableProcessor(); yield return new ScriptableObjectProcessor();
} }
public void Export(GameData gameData, string outputPath) public void Export(GameData gameData, string outputPath)

View File

@ -1,17 +1,17 @@
using AssetRipper.Assets; using AssetRipper.Assets;
using AssetRipper.Processing.Playable; using AssetRipper.Processing.ScriptableObject;
using AssetRipper.SourceGenerated.Classes.ClassID_114; using AssetRipper.SourceGenerated.Classes.ClassID_114;
namespace AssetRipper.Export.UnityProjects.Project; namespace AssetRipper.Export.UnityProjects.Project;
public class PlayableAssetYamlExporter : YamlExporterBase public class ScriptableObjectGroupExporter : YamlExporterBase
{ {
public override bool TryCreateCollection(IUnityObjectBase asset, [NotNullWhen(true)] out IExportCollection? exportCollection) public override bool TryCreateCollection(IUnityObjectBase asset, [NotNullWhen(true)] out IExportCollection? exportCollection)
{ {
switch (asset.MainAsset) switch (asset.MainAsset)
{ {
case PlayableAssetGroup playableAssetGroup: case ScriptableObjectGroup playableAssetGroup:
exportCollection = new PlayableAssetExportCollection(this, playableAssetGroup); exportCollection = new ScriptableObjectGroupExportCollection(this, playableAssetGroup);
return true; return true;
default: default:
exportCollection = null; exportCollection = null;
@ -19,10 +19,10 @@ public class PlayableAssetYamlExporter : YamlExporterBase
} }
} }
private sealed class PlayableAssetExportCollection : AssetsExportCollection<IMonoBehaviour> private sealed class ScriptableObjectGroupExportCollection : AssetsExportCollection<IMonoBehaviour>
{ {
public PlayableAssetGroup Group { get; } public ScriptableObjectGroup Group { get; }
public PlayableAssetExportCollection(PlayableAssetYamlExporter exporter, PlayableAssetGroup group) : base(exporter, group.Root) public ScriptableObjectGroupExportCollection(ScriptableObjectGroupExporter exporter, ScriptableObjectGroup group) : base(exporter, group.Root)
{ {
Group = group; Group = group;
AddAssets(group.Children); AddAssets(group.Children);
@ -30,7 +30,7 @@ public class PlayableAssetYamlExporter : YamlExporterBase
protected override string GetExportExtension(IUnityObjectBase asset) protected override string GetExportExtension(IUnityObjectBase asset)
{ {
return "playable"; return Group.FileExtension ?? base.GetExportExtension(asset);
} }
public override IEnumerable<IUnityObjectBase> Assets => base.Assets.Prepend(Group); public override IEnumerable<IUnityObjectBase> Assets => base.Assets.Prepend(Group);

View File

@ -16,7 +16,7 @@ using AssetRipper.Export.UnityProjects.Textures;
using AssetRipper.Import.AssetCreation; using AssetRipper.Import.AssetCreation;
using AssetRipper.Import.Structure.Assembly.Managers; using AssetRipper.Import.Structure.Assembly.Managers;
using AssetRipper.Mining.PredefinedAssets; using AssetRipper.Mining.PredefinedAssets;
using AssetRipper.Processing.Playable; using AssetRipper.Processing.ScriptableObject;
using AssetRipper.Processing.Textures; using AssetRipper.Processing.Textures;
using AssetRipper.SourceGenerated; using AssetRipper.SourceGenerated;
using AssetRipper.SourceGenerated.Classes.ClassID_1; using AssetRipper.SourceGenerated.Classes.ClassID_1;
@ -171,9 +171,9 @@ partial class ProjectExporter
OverrideExporter<IUnityObjectBase>(new AnimatorControllerExporter()); OverrideExporter<IUnityObjectBase>(new AnimatorControllerExporter());
//Playable assets //Playable assets
PlayableAssetYamlExporter playableAssetExporter = new(); ScriptableObjectGroupExporter scriptableObjectGroupExporter = new();
OverrideExporter<IMonoBehaviour>(playableAssetExporter); OverrideExporter<IMonoBehaviour>(scriptableObjectGroupExporter);
OverrideExporter<PlayableAssetGroup>(playableAssetExporter); OverrideExporter<ScriptableObjectGroup>(scriptableObjectGroupExporter);
} }
//These need to be absolutely last //These need to be absolutely last

View File

@ -2,11 +2,11 @@
using AssetRipper.Assets.Metadata; using AssetRipper.Assets.Metadata;
using AssetRipper.SourceGenerated.Classes.ClassID_114; using AssetRipper.SourceGenerated.Classes.ClassID_114;
namespace AssetRipper.Processing.Playable; namespace AssetRipper.Processing.ScriptableObject;
public sealed class PlayableAssetGroup : UnityObjectBase, INamed public sealed class ScriptableObjectGroup : UnityObjectBase, INamed
{ {
public PlayableAssetGroup(AssetInfo assetInfo, IMonoBehaviour root) : base(assetInfo) public ScriptableObjectGroup(AssetInfo assetInfo, IMonoBehaviour root) : base(assetInfo)
{ {
Root = root; Root = root;
} }
@ -18,6 +18,8 @@ public sealed class PlayableAssetGroup : UnityObjectBase, INamed
public Utf8String Name { get => Root.Name; set => throw new NotSupportedException(); } public Utf8String Name { get => Root.Name; set => throw new NotSupportedException(); }
public string? FileExtension { get; set; }
public void SetMainAssets() public void SetMainAssets()
{ {
MainAsset = this; MainAsset = this;

View File

@ -5,26 +5,38 @@ using AssetRipper.Import.Structure.Assembly.Serializable;
using AssetRipper.SourceGenerated.Classes.ClassID_114; using AssetRipper.SourceGenerated.Classes.ClassID_114;
using AssetRipper.SourceGenerated.Extensions; using AssetRipper.SourceGenerated.Extensions;
namespace AssetRipper.Processing.Playable; namespace AssetRipper.Processing.ScriptableObject;
public class PlayableProcessor : IAssetProcessor public class ScriptableObjectProcessor : IAssetProcessor
{ {
public void Process(GameData gameData) public void Process(GameData gameData)
{ {
Logger.Info(LogCategory.Processing, "Processing Playable Assets"); Logger.Info(LogCategory.Processing, "Processing Scriptable Object Groups");
ProcessedAssetCollection collection = gameData.AddNewProcessedCollection("Generated Playable Asset Groups"); ProcessedAssetCollection collection = gameData.AddNewProcessedCollection("Generated Scriptable Object Groups");
foreach (IMonoBehaviour monoBehaviour in gameData.GameBundle.FetchAssets().OfType<IMonoBehaviour>()) foreach (IMonoBehaviour monoBehaviour in gameData.GameBundle.FetchAssets().OfType<IMonoBehaviour>())
{ {
if (monoBehaviour.IsTimelineAsset()) if (monoBehaviour.IsTimelineAsset())
{ {
PlayableAssetGroup group = collection.CreateAsset(-1, monoBehaviour, static (assetInfo, root) => new PlayableAssetGroup(assetInfo, root)); ScriptableObjectGroup group = CreateGroup(collection, monoBehaviour);
group.Children.AddRange(FindChildren(monoBehaviour)); group.FileExtension = "playable";
group.Children.AddRange(FindTimelineAssetChildren(monoBehaviour));
group.SetMainAssets();
}
else if (monoBehaviour.IsPostProcessProfile())
{
ScriptableObjectGroup group = CreateGroup(collection, monoBehaviour);
group.Children.AddRange(FindPostProcessProfileChildren(monoBehaviour));
group.SetMainAssets(); group.SetMainAssets();
} }
} }
} }
private static IEnumerable<IMonoBehaviour> FindChildren(IMonoBehaviour root) private static ScriptableObjectGroup CreateGroup(ProcessedAssetCollection collection, IMonoBehaviour root)
{
return collection.CreateAsset(-1, root, static (assetInfo, root) => new ScriptableObjectGroup(assetInfo, root));
}
private static IEnumerable<IMonoBehaviour> FindTimelineAssetChildren(IMonoBehaviour root)
{ {
SerializableStructure? structure = LoadStructure(root); SerializableStructure? structure = LoadStructure(root);
if (structure is null) if (structure is null)
@ -84,6 +96,31 @@ public class PlayableProcessor : IAssetProcessor
return children; return children;
} }
private static IEnumerable<IMonoBehaviour> FindPostProcessProfileChildren(IMonoBehaviour root)
{
SerializableStructure? structure = LoadStructure(root);
if (structure is null)
{
return [];
}
HashSet<IMonoBehaviour> children = [];
if (structure.TryGetField("settings", out SerializableValue settings))
{
foreach (IPPtr pptr in settings.AsAssetArray.Cast<IPPtr>())
{
if (!root.Collection.TryGetAsset(pptr.FileID, pptr.PathID, out IMonoBehaviour? child))
{
continue;
}
children.Add(child);
}
}
return children;
}
private static SerializableStructure? LoadStructure(IMonoBehaviour monoBehaviour) private static SerializableStructure? LoadStructure(IMonoBehaviour monoBehaviour)
{ {
if (monoBehaviour.Structure is SerializableStructure structure) if (monoBehaviour.Structure is SerializableStructure structure)

View File

@ -50,6 +50,11 @@ public static class MonoBehaviourExtensions
return monoBehaviour.IsType("UnityEngine.Timeline", "TimelineAsset"); return monoBehaviour.IsType("UnityEngine.Timeline", "TimelineAsset");
} }
public static bool IsPostProcessProfile(this IMonoBehaviour monoBehaviour)
{
return monoBehaviour.IsType("UnityEngine.Rendering.PostProcessing", "PostProcessProfile");
}
private static bool IsType(this IMonoBehaviour monoBehaviour, string @namespace, string name) private static bool IsType(this IMonoBehaviour monoBehaviour, string @namespace, string name)
{ {
return TryGetScript(monoBehaviour, out IMonoScript? script) && script.IsType(@namespace, name); return TryGetScript(monoBehaviour, out IMonoScript? script) && script.IsType(@namespace, name);