Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
66641ae
Account for namespace change of UnityEditor.AssetImporters
foonix Jun 8, 2024
38730ae
Naive update pass on broken accessors for latest AssetTools.NET dev
foonix Jun 9, 2024
7238260
Updated DLL's for previous commit, manually built from dev branch.
foonix Jun 9, 2024
c835800
Update TPK file to one supported by this version of AssetsTools.
foonix Jun 10, 2024
2db0399
Switch to indexer's internal dot notation, as it does the same thing.
foonix Jun 10, 2024
a51b7e7
Rework AssetsReplacerFromMemory to ContentReplacerFromBuffer.
foonix Jun 13, 2024
5fef5e2
Get stuff to actually go in the bundle again.
foonix Jun 13, 2024
f3478d9
Cleanup some unused stuff and commented code.
foonix Jun 14, 2024
8c9b8f5
Get FileMap.json into the bundle again.
foonix Jun 14, 2024
6dee85c
It turns out file data wasn't actually going into the assetsfiles. (Just
foonix Jun 14, 2024
c10bdc1
Cleanup only: Cut down on intermediate locals, or group in a block so
foonix Jun 15, 2024
483857e
Fix Unity editor crash when loading the resulting bundle. Create oute…
foonix Jun 16, 2024
4ac7da5
Get bundle from scratch idea working.
foonix Jun 16, 2024
46ef377
Remove template bundle input now that it's not strictly needed.
foonix Jun 16, 2024
2b216c7
Implement a replacer that deferres serialization to intermediate byte[]
foonix Jun 16, 2024
5d1dafc
Remove the shipped template bundle, no longer needed.
foonix Jun 16, 2024
5476405
Use a temporary file for the intermediate assets file.
foonix Jun 16, 2024
0cddf14
Simplify out some duplicate arrays.
foonix Jun 17, 2024
3942cda
Add ability to look for dependencies in a PPtr<T> arrays, eg m_Depend…
foonix Jun 18, 2024
778f6e1
Quick fix for circular dependencies by treeting the tree root as a gr…
foonix Jun 18, 2024
c558618
Skip self for preload table.
foonix Jun 18, 2024
776f971
Avoid parsing some object classes that can't have dependencies.
foonix Jun 18, 2024
e856a14
Cleanup unneded file map preload entry.
foonix Jun 18, 2024
9d36af1
Cleanup obsolete jobs. Per discussion, these were just to clear out t…
foonix Jun 19, 2024
037b807
Fix missing FileMap.json entry
foonix Jun 19, 2024
675ed9d
Fix missing remap for PPtr arrays.
foonix Jun 19, 2024
e982f49
Initial work getting arrays like m_Components to parse.
foonix Jun 19, 2024
beb5d7e
Rework tree walking to search more arrays. Rework CreateCatalogBundle
foonix Jun 20, 2024
80199dd
Fix remapping self PPtrs
foonix Jun 20, 2024
37fef0f
Use the progress bars some more.
foonix Jun 20, 2024
89dd048
Get catalog importer working again.
foonix Jun 20, 2024
eee1cb7
Use ResourceManager names as catalog names when available.
foonix Jun 20, 2024
ee0a1a6
Skip dep parsing for ComputeShader.
foonix Jun 24, 2024
0b60fc6
Separate root objects out from objects only included as dependencies.
foonix Jun 25, 2024
480d38f
Only create CAB & json map entries for root objects.
foonix Jun 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions Editor/Assets/AssetTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@

namespace BundleKit.Assets
{
[DebuggerDisplay("{assetsFileInstance.name}/{name} fid:{FileId} pid:{PathId} children: {Children.Count}")]
[DebuggerDisplay("{assetExternal.file.name}/{name} fid:{FileId} pid:{PathId} children: {Children.Count}")]
public struct AssetTree : IEquatable<AssetTree>
{
public string name;
public AssetExternal assetExternal;
public string resourceManagerName;
public AssetExternal sourceData;
public int FileId;
public long PathId;
/// <summary>
/// List of dependencies in the dependency graph for the object has been resolved.
/// Null if dependencies are unknown.
/// </summary>
public List<AssetTree> Children;

public IEnumerable<(int fileId, long pathId)> FlattenIds(bool enterDependencies)
Expand All @@ -24,13 +29,17 @@ public struct AssetTree : IEquatable<AssetTree>
foreach (var result in child.FlattenIds(enterDependencies))
yield return result;
}
public IEnumerable<AssetTree> Flatten(bool enterDependencies)
public IEnumerable<AssetTree> WithDeps(bool enterDependencies)
{
yield return this;
foreach (var child in Children)
if (enterDependencies || child.FileId == 0)
foreach (var result in child.Flatten(enterDependencies))
yield return result;
if (enterDependencies)
foreach (var child in Children)
yield return child;
}

public string GetBkCatalogName()
{
return string.IsNullOrEmpty(resourceManagerName) ? name.ToLower() : resourceManagerName;
}

public override bool Equals(object obj)
Expand All @@ -40,14 +49,14 @@ public override bool Equals(object obj)

public bool Equals(AssetTree other)
{
return EqualityComparer<AssetsFileInstance>.Default.Equals(assetExternal.file, other.assetExternal.file) &&
return EqualityComparer<AssetsFileInstance>.Default.Equals(sourceData.file, other.sourceData.file) &&
PathId == other.PathId;
}

public override int GetHashCode()
{
int hashCode = -1120199924;
hashCode = hashCode * -1521134295 + EqualityComparer<AssetsFileInstance>.Default.GetHashCode(assetExternal.file);
hashCode = hashCode * -1521134295 + EqualityComparer<AssetsFileInstance>.Default.GetHashCode(sourceData.file);
hashCode = hashCode * -1521134295 + PathId.GetHashCode();
return hashCode;
}
Expand Down
36 changes: 35 additions & 1 deletion Editor/Assets/Filter.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,46 @@
using AssetsTools.NET.Extra;
using AssetsTools.NET;
using AssetsTools.NET.Extra;
using System;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine;

namespace BundleKit.Assets
{
[Serializable]
public struct Filter
{
[Tooltip("An object must have a name matching one of these expressions. Leave this list empty to match any name.")]
public string[] nameRegex;
[Tooltip("Unity built-in object class required for this filter to match. Use 'Object' to match any kind of object.")]
public AssetClassID assetClass;

private Regex[] regexCache;

public bool Match(AssetFileInfo assetFileInfo, string name)
{
if (!((AssetClassID)assetFileInfo.TypeId == assetClass))
{
return false;
}

// match all objects with the given class if not filtering by name.
if (nameRegex.Length == 0)
{
return true;
}

regexCache ??= nameRegex.Select(p => new Regex(p, RegexOptions.IgnoreCase)).ToArray();

foreach (var regex in regexCache)
{
if (regex.IsMatch(name))
{
return true;
}
}

return false;
}
}
}
2 changes: 1 addition & 1 deletion Templates.meta → Editor/Assets/Replacers.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 46 additions & 0 deletions Editor/Assets/Replacers/DeferredBaseFieldSerializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using AssetsTools.NET;
using System.IO;

namespace BundleKit.Assets.Replacers
{
/// <summary>
/// Serialize the provided AssetBaseValueField reference at write time. (Closure)
///
/// Use this to set up serialization on an aset that is still actively being manipulated,
/// or to defer generating the serialized byte[] until it's actually needed (and then can be GC'd)
/// </summary>
public class DeferredBaseFieldSerializer : IContentReplacer
{
private AssetTypeValueField baseField;
readonly private bool discardAfterWrite;

/// <summary>
/// Serialize baseField at write time, discarding the reference if discardAfterWrite is true.
///
/// Note that discarding the reference means the writer will only work once.
/// </summary>
/// <param name="baseField">Reference to the asset's base field</param>
/// <param name="discardAfterWrite">If true, the reference will be discarded after write so that it can be garbage collected.</param>
public DeferredBaseFieldSerializer(AssetTypeValueField baseField, bool discardAfterWrite = true)
{
this.baseField = baseField;
this.discardAfterWrite = discardAfterWrite;
}

public Stream GetPreviewStream() =>
throw new System.NotImplementedException();

public ContentReplacerType GetReplacerType() => ContentReplacerType.AddOrModify;

public bool HasPreview() => false;

public void Write(AssetsFileWriter writer)
{
writer.BaseStream.Write(baseField.WriteToByteArray(writer.BigEndian));
if (discardAfterWrite)
{
baseField = null;
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

75 changes: 75 additions & 0 deletions Editor/Assets/ResourceManagerDb.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using AssetsTools.NET;
using AssetsTools.NET.Extra;
using System.Collections.Generic;

namespace BundleKit.Assets
{
/// <summary>
/// Provides data queries into ResourceManager.
///
/// ResourceManager stores data for APIs such as Resources.Load() to function.
/// It stores the file paths, preload tables, and dependency information.
/// In a build, this data lives in globalgamemanagers.
/// </summary>
public class ResourceManagerDb
{
private readonly Dictionary<AssetId, string> assetToName = new();

private const string ggmFileName = "globalgamemanagers";

/// <summary>
/// Create ResourceManagerDb from the provied AssetsManager.
/// am must have already loaded globalgamemanagers.
/// </summary>
/// <param name="am">AssetsManager representing a game build, with globalgamemanagers file loaded.</param>
public ResourceManagerDb(AssetsManager am)
{
var ggmFileInstance = am.FileLookup[ggmFileName];
var rmInfo = ggmFileInstance.file.GetAssetsOfType(AssetClassID.ResourceManager)[0];
var rmBase = am.GetBaseField(ggmFileInstance, rmInfo);
var ggmExternals = ggmFileInstance.file.Metadata.Externals;

ParseMContainer(rmBase, ggmExternals);

// Skipping implementation for m_DependentAssets until it's needed
}

public string this[AssetId id] => assetToName[id];

public bool TryGetName(AssetId id, out string resourceManagerName)
=> assetToName.TryGetValue(id, out resourceManagerName);

public bool TryGetName(string assetsFileName, long pathIdInFile, out string resourceManagerName)
=> assetToName.TryGetValue(new AssetId(assetsFileName, pathIdInFile), out resourceManagerName);

private void ParseMContainer(AssetTypeValueField rmBase, List<AssetsFileExternal> ggmExternals)
{
var mContainer = rmBase["m_Container"];
foreach (var entry in mContainer.Children[0].Children)
{
string name = entry.Children[0].AsString;
int pathId = entry.Children[1].Children[0].AsInt;
long fileId = entry.Children[1].Children[1].AsLong;

if (pathId == 0)
{
// Some entries have m_FileID: 0, m_PathID: 0
// not sure what causes this, but may be a path for an asset that didn't go into the build.
continue;
}

string containerFileName;
if (pathId > 0)
{
containerFileName = ggmExternals[pathId - 1].OriginalPathName;
}
else
{
containerFileName = ggmFileName;
}

assetToName.Add(new AssetId(containerFileName, fileId), name);
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions Editor/BundleKit.Editor.asmdef
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
{
"name": "BundleKit.Editor",
"rootNamespace": "",
"references": [
"ThunderKit.Common",
"ThunderKit.Core",
"Unity.ScriptableBuildPipeline",
"Unity.ScriptableBuildPipeline.Editor"
],
"optionalUnityReferences": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"AssetsTools.NET.dll"
"AssetsTools.NET.dll",
"AssetsTools.NET.Texture.dll"
],
"autoReferenced": false,
"defineConstraints": []
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
6 changes: 3 additions & 3 deletions Editor/Bundles/Catalog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ public void Initialize()

var (bun, bundleAssetsFile, assetBundleExtAsset) = am.LoadBundle(path);

var bundleBaseField = assetBundleExtAsset.instance.GetBaseField();
var bundleName = bundleBaseField.GetValue("m_AssetBundleName").AsString();
var bundleBaseField = assetBundleExtAsset.baseField;
var bundleName = bundleBaseField["m_AssetBundleName"].AsString;

am.UnloadAll();

Expand All @@ -53,7 +53,7 @@ public void Initialize()
break;
}
}
var fileMapJson = bundle.LoadAsset<TextAsset>("FileMap");
var fileMapJson = bundle.LoadAsset<TextAsset>("BundleKitFileMap");
var fileMap = JsonUtility.FromJson<FileMap>(fileMapJson.text);
var lookup = fileMap.Maps.ToDictionary(element => element.LocalId, element => element.OriginId);

Expand Down
5 changes: 5 additions & 0 deletions Editor/Editors/SerializableMaterialDataImporterEditor.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
using BundleKit.Assets;
using BundleKit.Bundles;
using UnityEditor;
#if UNITY_2020_2_OR_NEWER
using UnityEditor.AssetImporters;
#else
using UnityEditor.Experimental.AssetImporters;
#endif

using UnityEditorInternal;
using UnityEngine;

Expand Down
16 changes: 10 additions & 6 deletions Editor/Importers/CatalogImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
using System.Linq;
using UnityEditor;
using UnityEditor.Build.Pipeline.Utilities;
#if UNITY_2020_2_OR_NEWER
using UnityEditor.AssetImporters;
#else
using UnityEditor.Experimental.AssetImporters;
#endif

using UnityEngine;
using Object = UnityEngine.Object;

Expand All @@ -27,11 +32,10 @@ public override void OnImportAsset(AssetImportContext ctx)

var (bun, bundleAssetsFile, assetBundleExtAsset) = am.LoadBundle(ctx.assetPath);

var bundleBaseField = assetBundleExtAsset.instance.GetBaseField();
var dependencyArray = bundleBaseField.GetField("m_Dependencies/Array");
var dependencies = dependencyArray.GetChildrenList().Select(dep => dep.GetValue().AsString()).ToArray();
var container = bundleBaseField.GetField("m_Container/Array");
var bundleName = bundleBaseField.GetValue("m_AssetBundleName").AsString();
var bundleBaseField = assetBundleExtAsset.baseField;
var dependencyArray = bundleBaseField["m_Dependencies.Array"];
var container = bundleBaseField["m_Container.Array"];
var bundleName = bundleBaseField["m_AssetBundleName"].AsString;

am.UnloadAll();

Expand Down Expand Up @@ -60,7 +64,7 @@ public override void OnImportAsset(AssetImportContext ctx)
for (int i = 0; i < allAssets.Length; i++)
{
var asset = allAssets[i];
if (asset.name == "FileMap") continue;
if (asset.name == "BundleKitFileMap") continue;
if (asset is Shader shader)
{
ShaderUtil.RegisterShader(shader);
Expand Down
5 changes: 5 additions & 0 deletions Editor/Importers/SerializableMaterialDataImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
using System.IO;
using System.Linq;
using UnityEditor;
#if UNITY_2020_2_OR_NEWER
using UnityEditor.AssetImporters;
#else
using UnityEditor.Experimental.AssetImporters;
#endif

using UnityEngine;

namespace BundleKit.Bundles
Expand Down
Loading