Initial Commit

This commit is contained in:
2026-03-16 14:38:46 +02:00
commit b8f7327a21
2327 changed files with 253610 additions and 0 deletions
@@ -0,0 +1,68 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ModestTree;
using UnityEditorInternal;
using UnityEngine;
namespace Zenject.ReflectionBaking
{
public class AssemblyPathRegistry
{
static List<string> _assemblies;
public static List<string> GetAllGeneratedAssemblyRelativePaths()
{
if (_assemblies == null)
{
_assemblies = LookupAllGeneratedAssemblyPaths();
Assert.IsNotNull(_assemblies);
}
return _assemblies;
}
static bool IsManagedAssembly(string systemPath)
{
DllType dllType = InternalEditorUtility.DetectDotNetDll(systemPath);
return dllType != DllType.Unknown && dllType != DllType.Native;
}
static List<string> LookupAllGeneratedAssemblyPaths()
{
var assemblies = new List<string>(20);
// We could also add the ones in the project but we probably don't want to edit those
//FindAssemblies(Application.dataPath, 120, assemblies);
FindAssemblies(Application.dataPath + "/../Library/ScriptAssemblies/", 2, assemblies);
return assemblies;
}
public static void FindAssemblies(string systemPath, int maxDepth, List<string> result)
{
if (maxDepth > 0)
{
if (Directory.Exists(systemPath))
{
var dirInfo = new DirectoryInfo(systemPath);
result.AddRange(
dirInfo.GetFiles().Select(x => x.FullName)
.Where(IsManagedAssembly)
.Select(ReflectionBakingInternalUtil.ConvertAbsoluteToAssetPath));
var directories = dirInfo.GetDirectories();
for (int i = 0; i < directories.Length; i++)
{
DirectoryInfo current = directories[i];
FindAssemblies(current.FullName, maxDepth - 1, result);
}
}
}
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: f96372c95411c904bb55ba67b55e0c84
timeCreated: 1537003252
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,107 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using ModestTree;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;
using Zenject.ReflectionBaking.Mono.Cecil;
using Debug = UnityEngine.Debug;
namespace Zenject.ReflectionBaking
{
public static class ReflectionBakingBuildObserver
{
[InitializeOnLoadMethod]
public static void Initialize()
{
CompilationPipeline.assemblyCompilationFinished += OnAssemblyCompiled;
}
static void OnAssemblyCompiled(string assemblyAssetPath, CompilerMessage[] messages)
{
#if !UNITY_2018_1_OR_NEWER
if (Application.isEditor && !BuildPipeline.isBuildingPlayer)
{
return;
}
#endif
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.WSAPlayer)
{
Log.Warn("Zenject reflection baking skipped because it is not currently supported on WSA platform!");
}
else
{
TryWeaveAssembly(assemblyAssetPath);
}
}
static void TryWeaveAssembly(string assemblyAssetPath)
{
var settings = ReflectionBakingInternalUtil.TryGetEnabledSettingsInstance();
if (settings == null)
{
return;
}
if (settings.AllGeneratedAssemblies && settings.ExcludeAssemblies.Contains(assemblyAssetPath))
{
return;
}
if (!settings.AllGeneratedAssemblies && !settings.IncludeAssemblies.Contains(assemblyAssetPath))
{
return;
}
var stopwatch = new Stopwatch();
stopwatch.Start();
var assemblyFullPath = ReflectionBakingInternalUtil.ConvertAssetPathToSystemPath(assemblyAssetPath);
var readerParameters = new ReaderParameters
{
AssemblyResolver = new UnityAssemblyResolver(),
// Is this necessary?
//ReadSymbols = true,
};
var module = ModuleDefinition.ReadModule(assemblyFullPath, readerParameters);
var assemblyRefNames = module.AssemblyReferences.Select(x => x.Name.ToLower()).ToList();
if (!assemblyRefNames.Contains("zenject-usage"))
{
// Zenject-usage is used by the generated methods
// Important that we do this check otherwise we can corrupt some dlls that don't have access to it
return;
}
var assemblyName = Path.GetFileNameWithoutExtension(assemblyAssetPath);
var assembly = AppDomain.CurrentDomain.GetAssemblies()
.Where(x => x.GetName().Name == assemblyName).OnlyOrDefault();
Assert.IsNotNull(assembly, "Could not find unique assembly '{0}' in currently loaded list of assemblies", assemblyName);
int numTypesChanged = ReflectionBakingModuleEditor.WeaveAssembly(
module, assembly, settings.NamespacePatterns);
if (numTypesChanged > 0)
{
var writerParams = new WriterParameters()
{
// Is this necessary?
//WriteSymbols = true
};
module.Write(assemblyFullPath, writerParams);
Debug.Log("Added reflection baking to '{0}' types in assembly '{1}', took {2:0.00} seconds"
.Fmt(numTypesChanged, Path.GetFileName(assemblyAssetPath), stopwatch.Elapsed.TotalSeconds));
}
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 374dbffd3e3c6504489ada7d14aa4006
timeCreated: 1537501691
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,78 @@
using System;
using System.IO;
using System.Reflection;
using ModestTree;
using UnityEditor;
using UnityEngine;
namespace Zenject.ReflectionBaking
{
public static class ReflectionBakingInternalUtil
{
public static string ConvertAssetPathToSystemPath(string assetPath)
{
string path = Application.dataPath;
int pathLength = path.Length;
path = path.Substring(0, pathLength - /* Assets */ 6);
path = Path.Combine(path, assetPath);
return path;
}
public static ZenjectReflectionBakingSettings TryGetEnabledSettingsInstance()
{
string[] guids = AssetDatabase.FindAssets("t:ZenjectReflectionBakingSettings");
if (guids.IsEmpty())
{
return null;
}
ZenjectReflectionBakingSettings enabledSettings = null;
foreach (var guid in guids)
{
var candidate = AssetDatabase.LoadAssetAtPath<ZenjectReflectionBakingSettings>(
AssetDatabase.GUIDToAssetPath(guid));
if ((Application.isEditor && candidate.IsEnabledInEditor) || (BuildPipeline.isBuildingPlayer && candidate.IsEnabledInBuilds))
{
Assert.IsNull(enabledSettings, "Found multiple enabled ZenjectReflectionBakingSettings objects! Please disable/delete one to continue.");
enabledSettings = candidate;
}
}
return enabledSettings;
}
public static string ConvertAbsoluteToAssetPath(string systemPath)
{
var projectPath = Application.dataPath;
// Remove 'Assets'
projectPath = projectPath.Substring(0, projectPath.Length - /* Assets */ 6);
int systemPathLength = systemPath.Length;
int assetPathLength = systemPathLength - projectPath.Length;
Assert.That(assetPathLength > 0, "Unexpect path '{0}'", systemPath);
return systemPath.Substring(projectPath.Length, assetPathLength);
}
public static void TryForceUnityFullCompile()
{
Type compInterface = typeof(UnityEditor.Editor).Assembly.GetType(
"UnityEditor.Scripting.ScriptCompilation.EditorCompilationInterface");
if (compInterface != null)
{
var dirtyAllScriptsMethod = compInterface.GetMethod(
"DirtyAllScripts", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
dirtyAllScriptsMethod.Invoke(null, null);
}
UnityEditor.AssetDatabase.Refresh();
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 68724c9557073844fb7c3f088c588d32
timeCreated: 1537003252
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,24 @@
#if !NOT_UNITY3D
using System.IO;
using UnityEditor;
using UnityEngine;
using Zenject.Internal;
namespace Zenject.ReflectionBaking
{
public static class ReflectionBakingMenuItems
{
[MenuItem("Assets/Create/Zenject/Reflection Baking Settings", false, 100)]
public static void CreateReflectionBakingSettings()
{
var folderPath = ZenUnityEditorUtil.GetCurrentDirectoryAssetPathFromSelection();
var config = ScriptableObject.CreateInstance<ZenjectReflectionBakingSettings>();
ZenUnityEditorUtil.SaveScriptableObjectAsset(
Path.Combine(folderPath, "ZenjectReflectionBakingSettings.asset"), config);
}
}
}
#endif
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 549215a3ba27806449b2b1542fdffc03
timeCreated: 1537690031
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Zenject.ReflectionBaking.Mono.Cecil;
namespace Zenject.ReflectionBaking
{
public class UnityAssemblyResolver : BaseAssemblyResolver
{
readonly IDictionary<string, string> _appDomainAssemblyLocations;
readonly IDictionary<string, AssemblyDefinition> _cache;
public UnityAssemblyResolver()
{
_appDomainAssemblyLocations = new Dictionary<string, string>();
_cache = new Dictionary<string, AssemblyDefinition>();
AppDomain domain = AppDomain.CurrentDomain;
Assembly[] assemblies = domain.GetAssemblies();
for (int i = 0; i < assemblies.Length; i++)
{
#if NET_4_6
if (assemblies[i].IsDynamic)
{
continue;
}
#endif
_appDomainAssemblyLocations[assemblies[i].FullName] = assemblies[i].Location;
AddSearchDirectory(Path.GetDirectoryName(assemblies[i].Location));
}
}
public override AssemblyDefinition Resolve(AssemblyNameReference name)
{
AssemblyDefinition assemblyDef = FindAssemblyDefinition(name.FullName, null);
if (assemblyDef == null)
{
assemblyDef = base.Resolve(name);
_cache[name.FullName] = assemblyDef;
}
return assemblyDef;
}
public override AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
{
AssemblyDefinition assemblyDef = FindAssemblyDefinition(name.FullName, parameters);
if (assemblyDef == null)
{
assemblyDef = base.Resolve(name, parameters);
_cache[name.FullName] = assemblyDef;
}
return assemblyDef;
}
/// Searches for AssemblyDefinition in our cache, and failing that,
/// looks for a known location. Returns null if both attempts fail.
AssemblyDefinition FindAssemblyDefinition(string fullName, ReaderParameters parameters)
{
if (fullName == null)
{
throw new ArgumentNullException("fullName");
}
AssemblyDefinition assemblyDefinition;
// Look in cache first
if (_cache.TryGetValue(fullName, out assemblyDefinition))
{
return assemblyDefinition;
}
// Try to use known location
string location;
if (_appDomainAssemblyLocations.TryGetValue(fullName, out location))
{
if (parameters != null)
{
assemblyDefinition = AssemblyDefinition.ReadAssembly(location, parameters);
}
else
{
assemblyDefinition = AssemblyDefinition.ReadAssembly(location);
}
_cache[fullName] = assemblyDefinition;
return assemblyDefinition;
}
return null;
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: b107233111f831043b3d5983fe6f1b25
timeCreated: 1537934945
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,56 @@
using System.Collections.Generic;
using UnityEngine;
namespace Zenject.ReflectionBaking
{
public class ZenjectReflectionBakingSettings : ScriptableObject
{
[SerializeField]
bool _isEnabledInBuilds = true;
[SerializeField]
bool _isEnabledInEditor = false;
[SerializeField]
bool _allGeneratedAssemblies = true;
[SerializeField]
List<string> _includeAssemblies = null;
[SerializeField]
List<string> _excludeAssemblies = null;
[SerializeField]
List<string> _namespacePatterns = null;
public List<string> NamespacePatterns
{
get { return _namespacePatterns; }
}
public List<string> IncludeAssemblies
{
get { return _includeAssemblies; }
}
public List<string> ExcludeAssemblies
{
get { return _excludeAssemblies; }
}
public bool IsEnabledInEditor
{
get { return _isEnabledInEditor; }
}
public bool IsEnabledInBuilds
{
get { return _isEnabledInBuilds; }
}
public bool AllGeneratedAssemblies
{
get { return _allGeneratedAssemblies; }
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 1ab372d6a005c8344b5d6b25dbc310ce
timeCreated: 1536333743
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,236 @@
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
namespace Zenject.ReflectionBaking
{
[CustomEditor(typeof(ZenjectReflectionBakingSettings))]
public class ZenjectReflectionBakingSettingsEditor : Editor
{
SerializedProperty _includeAssemblies;
SerializedProperty _excludeAssemblies;
SerializedProperty _namespacePatterns;
SerializedProperty _isEnabledInBuilds;
SerializedProperty _isEnabledInEditor;
SerializedProperty _allGeneratedAssemblies;
// Lists
ReorderableList _includeAssembliesList;
ReorderableList _excludeAssembliesList;
ReorderableList _namespacePatternsList;
// Layouts
Vector2 _logScrollPosition;
int _selectedLogIndex;
bool _hasModifiedProperties;
static GUIContent _includeAssembliesListHeaderContent = new GUIContent
{
text = "Include Assemblies",
tooltip = "The list of all the assemblies that will be editted to have reflection information directly embedded"
};
static GUIContent _excludeAssembliesListHeaderContent = new GUIContent
{
text = "Exclude Assemblies",
tooltip = "The list of all the assemblies that will not be editted"
};
static GUIContent _namespacePatternListHeaderContent = new GUIContent
{
text = "Namespace Patterns",
tooltip = "This list of Regex patterns will be compared to the name of each type in the given assemblies, and when a match is found that type will be editting to directly contain reflection information"
};
void OnEnable()
{
_includeAssemblies = serializedObject.FindProperty("_includeAssemblies");
_excludeAssemblies = serializedObject.FindProperty("_excludeAssemblies");
_namespacePatterns = serializedObject.FindProperty("_namespacePatterns");
_isEnabledInEditor = serializedObject.FindProperty("_isEnabledInEditor");
_isEnabledInBuilds = serializedObject.FindProperty("_isEnabledInBuilds");
_allGeneratedAssemblies = serializedObject.FindProperty("_allGeneratedAssemblies");
_namespacePatternsList = new ReorderableList(serializedObject, _namespacePatterns);
_namespacePatternsList.drawHeaderCallback += OnNamespacePatternsDrawHeader;
_namespacePatternsList.drawElementCallback += OnNamespacePatternsDrawElement;
_includeAssembliesList = new ReorderableList(serializedObject, _includeAssemblies);
_includeAssembliesList.drawHeaderCallback += OnIncludeWeavedAssemblyDrawHeader;
_includeAssembliesList.onAddCallback += OnIncludeWeavedAssemblyElementAdded;
_includeAssembliesList.drawElementCallback += OnIncludeAssemblyListDrawElement;
_excludeAssembliesList = new ReorderableList(serializedObject, _excludeAssemblies);
_excludeAssembliesList.drawHeaderCallback += OnExcludeWeavedAssemblyDrawHeader;
_excludeAssembliesList.onAddCallback += OnExcludeWeavedAssemblyElementAdded;
_excludeAssembliesList.drawElementCallback += OnExcludeAssemblyListDrawElement;
}
void OnNamespacePatternsDrawElement(Rect rect, int index, bool isActive, bool isFocused)
{
SerializedProperty indexProperty = _namespacePatterns.GetArrayElementAtIndex(index);
indexProperty.stringValue = EditorGUI.TextField(rect, indexProperty.stringValue);
}
void OnExcludeAssemblyListDrawElement(Rect rect, int index, bool isActive, bool isFocused)
{
SerializedProperty indexProperty = _excludeAssemblies.GetArrayElementAtIndex(index);
EditorGUI.LabelField(rect, indexProperty.stringValue, EditorStyles.textArea);
}
void OnIncludeAssemblyListDrawElement(Rect rect, int index, bool isActive, bool isFocused)
{
SerializedProperty indexProperty = _includeAssemblies.GetArrayElementAtIndex(index);
EditorGUI.LabelField(rect, indexProperty.stringValue, EditorStyles.textArea);
}
void OnNamespacePatternsDrawHeader(Rect rect)
{
GUI.Label(rect, _namespacePatternListHeaderContent);
}
void OnExcludeWeavedAssemblyDrawHeader(Rect rect)
{
GUI.Label(rect, _excludeAssembliesListHeaderContent);
}
void OnIncludeWeavedAssemblyDrawHeader(Rect rect)
{
GUI.Label(rect, _includeAssembliesListHeaderContent);
}
public override void OnInspectorGUI()
{
EditorGUI.BeginChangeCheck();
{
GUILayout.Label("Settings", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_isEnabledInBuilds, true);
var oldIsEnabledInEditorValue = _isEnabledInEditor.boolValue;
EditorGUILayout.PropertyField(_isEnabledInEditor, true);
if (oldIsEnabledInEditorValue != _isEnabledInEditor.boolValue)
{
ReflectionBakingInternalUtil.TryForceUnityFullCompile();
}
#if !UNITY_2018_1_OR_NEWER
if (_isEnabledInEditor.boolValue)
{
EditorGUILayout.HelpBox(
"Reflection baking inside unity editor requires Unity 2018+! It is however supported for builds", MessageType.Error);
}
#endif
EditorGUILayout.PropertyField(_allGeneratedAssemblies, true);
if (_allGeneratedAssemblies.boolValue)
{
_excludeAssembliesList.DoLayoutList();
GUI.enabled = false;
try
{
_includeAssembliesList.DoLayoutList();
}
finally
{
GUI.enabled = true;
}
}
else
{
GUI.enabled = false;
try
{
_excludeAssembliesList.DoLayoutList();
}
finally
{
GUI.enabled = true;
}
_includeAssembliesList.DoLayoutList();
}
_namespacePatternsList.DoLayoutList();
}
if (EditorGUI.EndChangeCheck())
{
_hasModifiedProperties = true;
}
if (_hasModifiedProperties)
{
_hasModifiedProperties = false;
ApplyModifiedProperties();
}
}
void ApplyModifiedProperties()
{
serializedObject.ApplyModifiedProperties();
serializedObject.Update();
}
void OnExcludeWeavedAssemblyElementAdded(ReorderableList list)
{
OnAssemblyElementAdded(_excludeAssemblies, list);
}
void OnIncludeWeavedAssemblyElementAdded(ReorderableList list)
{
OnAssemblyElementAdded(_includeAssemblies, list);
}
void OnAssemblyElementAdded(SerializedProperty listProperty, ReorderableList list)
{
GenericMenu menu = new GenericMenu();
var paths = AssemblyPathRegistry.GetAllGeneratedAssemblyRelativePaths();
for (int i = 0; i < paths.Count; i++)
{
var path = paths[i];
bool foundMatch = false;
for (int k = 0; k < listProperty.arraySize; k++)
{
SerializedProperty current = listProperty.GetArrayElementAtIndex(k);
if (path == current.stringValue)
{
foundMatch = true;
break;
}
}
if (!foundMatch)
{
GUIContent content = new GUIContent(path);
menu.AddItem(content, false, p => OnWeavedAssemblyAdded(listProperty, p), path);
}
}
if (menu.GetItemCount() == 0)
{
menu.AddDisabledItem(new GUIContent("[All Assemblies Added]"));
}
menu.ShowAsContext();
}
void OnWeavedAssemblyAdded(SerializedProperty listProperty, object path)
{
listProperty.arraySize++;
SerializedProperty weaved = listProperty.GetArrayElementAtIndex(listProperty.arraySize - 1);
weaved.stringValue = ((string)path).Replace("\\", "/");
ApplyModifiedProperties();
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 90683e755a104ed4ab5841ef7bb58742
timeCreated: 1538185954
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: