private static void AddUndocumentApis(UnityApi unityApi, Version apiVersion) { // From AssetPostprocessingInternal var type = unityApi.FindType("AssetPostprocessor"); var eventFunction = new UnityApiEventFunction("OnPreprocessAssembly", false, ApiType.Void, apiVersion, undocumented: true); eventFunction.AddParameter("pathName", ApiType.String); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("OnGeneratedCSProjectFiles", true, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // Technically, return type is optional eventFunction = new UnityApiEventFunction("OnPreGeneratingCSProjectFiles", true, ApiType.Bool, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // From AssetModificationProcessorInternal type = unityApi.FindType("AssetModificationProcessor"); eventFunction = new UnityApiEventFunction("OnStatusUpdated", true, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // ScriptableObject // From Shawn White @ Unity (https://github.com/JetBrains/resharper-unity/issues/79#issuecomment-266727851): // OnValidate's behavior on ScriptableObject is the same as on MonoBehaviour. OnValidate is a non-static // method which is invoked from native and isn't picky about visibility (it'll get invoked regardless of // visibility). OnValidate is different from the other magic methods in that it only gets invoked from // the Editor. A good practice is to wrap OnValidate with #if UNITY_EDITOR so that the function can be // stripped out for deployment. // // To expand on ScriptableObject a bit. Native Unity code doesn't distinguish between MonoBehaviour and // ScriptableObject. They are the same native type (it's confusing, I know, and everyone gets tripped up // by it that looks at the native code base). The only difference is in how the object is used, // MonoBehaviours live on GameObjects, while ScriptableObjects can live alone.So in general, all magic // methods that would make sense without a GameObject context should work and be implemented for // ScriptableObjects. Off the top of my head this includes, Awake, OnEnable, OnDisable, OnDestroy, // OnValidate, and Reset, but there could be more. type = unityApi.FindType("ScriptableObject"); eventFunction = new UnityApiEventFunction("OnValidate", false, ApiType.Void, apiVersion, description: "This function is called when the script is loaded or a value is changed in the inspector (Called in the editor only).", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("Reset", false, ApiType.Void, apiVersion, description: "Reset to default values.", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); }
private static void AddUndocumentedCoroutines(UnityApi unityApi) { Console.WriteLine("Adding undocumented coroutines"); var type = unityApi.FindType("MonoBehaviour"); if (type != null) { // Not documented directly, but shown in examples // https://docs.unity3d.com/ScriptReference/MonoBehaviour.StartCoroutine.html // https://docs.unity3d.com/ScriptReference/WaitForEndOfFrame.html SetIsCoroutine(type, "Start"); // Not documented as co-routines, but the non-2D versions are SetIsCoroutine(type, "OnCollisionEnter2D"); SetIsCoroutine(type, "OnCollisionExit2D"); SetIsCoroutine(type, "OnCollisionStay2D"); SetIsCoroutine(type, "OnTriggerEnter2D"); SetIsCoroutine(type, "OnTriggerExit2D"); SetIsCoroutine(type, "OnTriggerStay2D"); } }
public static void Main(string[] args) { var progPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); var dataPath = Path.Combine(progPath, @"Unity\Editor\Data"); var monoPath = Path.Combine(dataPath, @"Mono\lib\mono\unity"); var basePath = Path.Combine(dataPath, @"Managed"); TypeResolver.AddAssembly(typeof(string).Assembly); TypeResolver.AddAssembly(Assembly.LoadFrom(Path.Combine(basePath, @"UnityEngine.dll"))); TypeResolver.AddAssembly(Assembly.LoadFrom(Path.Combine(monoPath, @"UnityScript.dll"))); TypeResolver.AddAssembly(Assembly.LoadFrom(Path.Combine(basePath, @"UnityEditor.dll"))); Console.WriteLine(); var unityApi = new UnityApi(); var parser = new ApiParser(unityApi, ScriptReferenceRelativePath); parser.Progress += (s, e) => { var cursorTop = Console.CursorTop; Console.WriteLine("{0,5} / {1,5} ({2,3}%)", e.Current, e.Total, e.Percent); Console.SetCursorPosition(0, cursorTop); }; foreach (var doc in Docs) { Console.WriteLine(doc.Item1); parser.ParseFolder(doc.Item1, doc.Item2); AddUndocumentApis(unityApi, doc.Item2); } using (var writer = new XmlTextWriter(@"api.xml", Encoding.UTF8) {Formatting = Formatting.Indented}) { parser.ExportTo(writer); } // Console.WriteLine( "Press <Enter> key to continue..." ); // Console.ReadLine(); }
public ApiParser(UnityApi api, string scriptReferenceRelativePath) { myApi = api; myScriptReferenceRelativePath = scriptReferenceRelativePath; }
public ApiParser(UnityApi api, TypeResolver typeResolver) { myApi = api; myTypeResolver = typeResolver; }
public ApiParser(UnityApi api) { myApi = api; }
public ApiParser(UnityApi api, string scriptReferenceRelativePath) { this.api = api; myScriptReferenceRelativePath = scriptReferenceRelativePath; }
public static void Main(string[] args) { if (args.Length != 1) { Console.WriteLine("Usage: ApiParser.exe docsFolder"); Console.WriteLine(); Console.WriteLine(" docsFolder - folder that contains all versions of Unity docs"); return; } var stopwatch = Stopwatch.StartNew(); Directory.SetCurrentDirectory(args[0]); var progPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); var managedPath = Path.Combine(progPath, "Unity", "Editor", "Data", "Managed"); if (!Directory.Exists(managedPath)) { // TODO: Find the latest version rather than hardcode it // TODO: Handle this in Windows, too //managedPath = Path.Combine(progPath, "Unity", "Hub", "Editor", "2018.1.0b9", "Unity.app", "Contents", "Managed"); managedPath = Path.Combine(progPath, "Unity", "Hub", "Editor", "2017.3.1f1", "Unity.app", "Contents", "Managed"); } // Add assemblies to the type resolver so we can get the fully qualified names of types // The Unity docs only give us the short names TypeResolver.AddAssembly(Assembly.LoadFrom(Path.Combine(managedPath, @"UnityEngine.dll"))); TypeResolver.AddAssembly(Assembly.LoadFrom(Path.Combine(managedPath, @"UnityEditor.dll"))); Console.WriteLine(); var unityApi = new UnityApi(); var parser = new ApiParser(unityApi, ScriptReferenceRelativePath); parser.Progress += (s, e) => { var cursorTop = Console.CursorTop; Console.WriteLine("{0,5} / {1,5} ({2,3}%)", e.Current, e.Total, e.Percent); Console.SetCursorPosition(0, cursorTop); }; foreach (var doc in Docs) { Console.WriteLine(doc.Item1); parser.ParseFolder(doc.Item1, doc.Item2); // These are valid for all versions AddUndocumentedApis(unityApi, doc.Item2); } // THese modify existing functions AddUndocumentedOptionalParameters(unityApi); AddUndocumentedCoroutines(unityApi); FixDataFromIncorrectDocs(unityApi); using (var writer = new XmlTextWriter(@"api.xml", Encoding.UTF8) { Formatting = Formatting.Indented }) { parser.ExportTo(writer); } Console.WriteLine("Done. Elapsed time: {0}", stopwatch.Elapsed); // Console.WriteLine( "Press <Enter> key to continue..." ); // Console.ReadLine(); }
private static void AddUndocumentedApis(UnityApi unityApi, Version apiVersion) { // From AssetPostprocessingInternal var type = unityApi.FindType("AssetPostprocessor"); if (type != null) { var eventFunction = new UnityApiEventFunction("OnPreprocessAssembly", false, false, ApiType.Void, apiVersion, undocumented: true); eventFunction.AddParameter("pathName", ApiType.String); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("OnGeneratedCSProjectFiles", true, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // Technically, return type is optional eventFunction = new UnityApiEventFunction("OnPreGeneratingCSProjectFiles", true, false, ApiType.Bool, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); } // From AssetModificationProcessorInternal type = unityApi.FindType("AssetModificationProcessor"); if (type != null) { var eventFunction = new UnityApiEventFunction("OnStatusUpdated", true, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); } type = unityApi.FindType("MonoBehaviour"); if (type != null) { const string description = "This callback is called if an associated RectTransform has its dimensions changed."; var eventFunction = new UnityApiEventFunction("OnRectTransformDimensionsChange", false, false, ApiType.Void, apiVersion, description, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("OnBeforeTransformParentChanged", false, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("OnDidApplyAnimationProperties", false, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("OnCanvasGroupChanged", false, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("OnCanvasHierarchyChanged", false, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); } // ScriptableObject // From Shawn White @ Unity (https://github.com/JetBrains/resharper-unity/issues/79#issuecomment-266727851): // OnValidate's behavior on ScriptableObject is the same as on MonoBehaviour. OnValidate is a non-static // method which is invoked from native and isn't picky about visibility (it'll get invoked regardless of // visibility). OnValidate is different from the other magic methods in that it only gets invoked from // the Editor. A good practice is to wrap OnValidate with #if UNITY_EDITOR so that the function can be // stripped out for deployment. // // To expand on ScriptableObject a bit. Native Unity code doesn't distinguish between MonoBehaviour and // ScriptableObject. They are the same native type (it's confusing, I know, and everyone gets tripped up // by it that looks at the native code base). The only difference is in how the object is used, // MonoBehaviours live on GameObjects, while ScriptableObjects can live alone.So in general, all magic // methods that would make sense without a GameObject context should work and be implemented for // ScriptableObjects. Off the top of my head this includes, Awake, OnEnable, OnDisable, OnDestroy, // OnValidate, and Reset, but there could be more. type = unityApi.FindType("ScriptableObject"); if (type != null) { var eventFunction = new UnityApiEventFunction("OnValidate", false, false, ApiType.Void, apiVersion, description: "This function is called when the script is loaded or a value is changed in the inspector (Called in the editor only).", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("Reset", false, false, ApiType.Void, apiVersion, description: "Reset to default values.", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); } }
private static void AddUndocumentedApis(UnityApi unityApi, Version apiVersion) { // From AssetPostprocessingInternal var type = unityApi.FindType("AssetPostprocessor"); if (type != null) { var eventFunction = new UnityApiEventFunction("OnPreprocessAssembly", false, false, ApiType.Void, apiVersion, undocumented: true); eventFunction.AddParameter("pathName", ApiType.String); type.MergeEventFunction(eventFunction, apiVersion); // From GitHub. Love the optimism in this one :) // https://github.com/Unity-Technologies/UnityCsReference/blob/96187e5fc1a23847206bf66b6f2d0e4a1ad43301/Editor/Mono/AssetPostprocessor.cs#L96 var description = "This is undocumented, and a 'safeguard' for when Visual Studio gets a new release that " + "is incompatible with Unity, so that users can postprocess our csproj files to fix the issue (or " + "just completely replace them). Hopefully we'll never need this."; eventFunction = new UnityApiEventFunction("OnGeneratedCSProjectFiles", true, false, ApiType.Void, apiVersion, description, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // Technically, return type is optional // https://github.com/Unity-Technologies/UnityCsReference/blob/96187e5fc1a23847206bf66b6f2d0e4a1ad43301/Editor/Mono/AssetPostprocessor.cs#L138 description = "This callback is used by UnityVS to take over project generation from Unity"; eventFunction = new UnityApiEventFunction("OnPreGeneratingCSProjectFiles", true, false, ApiType.Bool, apiVersion, description, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // These two were added in 2018.1, as verified on GitHub // https://github.com/Unity-Technologies/UnityCsReference/blob/2017.4/Editor/Mono/AssetPostprocessor.cs // https://github.com/Unity-Technologies/UnityCsReference/blob/2018.1/Editor/Mono/AssetPostprocessor.cs#L76 if (apiVersion >= new Version(2018, 1)) { // Technically, return type is optional // https://github.com/Unity-Technologies/UnityCsReference/blob/96187e5fc1a23847206bf66b6f2d0e4a1ad43301/Editor/Mono/AssetPostprocessor.cs#L123 description = "This callback is used by C# code editors to modify the .csproj files."; eventFunction = new UnityApiEventFunction("OnGeneratedCSProject", true, false, ApiType.String, apiVersion, description, undocumented: true); eventFunction.AddParameter("path", ApiType.String); eventFunction.AddParameter("content", ApiType.String); type.MergeEventFunction(eventFunction, apiVersion); // Technically, return type is optional // https://github.com/Unity-Technologies/UnityCsReference/blob/96187e5fc1a23847206bf66b6f2d0e4a1ad43301/Editor/Mono/AssetPostprocessor.cs#L108 description = "This callback is used by C# code editors to modify the .sln file"; eventFunction = new UnityApiEventFunction("OnGeneratedSlnSolution", true, false, ApiType.String, apiVersion, description, undocumented: true); eventFunction.AddParameter("path", ApiType.String); eventFunction.AddParameter("content", ApiType.String); type.MergeEventFunction(eventFunction, apiVersion); } } // From AssetModificationProcessorInternal type = unityApi.FindType("AssetModificationProcessor"); if (type != null) { var eventFunction = new UnityApiEventFunction("OnStatusUpdated", true, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); } type = unityApi.FindType("MonoBehaviour"); if (type != null) { const string description = "This callback is called if an associated RectTransform has its dimensions changed."; var eventFunction = new UnityApiEventFunction("OnRectTransformDimensionsChange", false, false, ApiType.Void, apiVersion, description, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("OnBeforeTransformParentChanged", false, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("OnDidApplyAnimationProperties", false, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("OnCanvasGroupChanged", false, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("OnCanvasHierarchyChanged", false, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); } // ScriptableObject // From Shawn White @ Unity (https://github.com/JetBrains/resharper-unity/issues/79#issuecomment-266727851): // OnValidate's behavior on ScriptableObject is the same as on MonoBehaviour. OnValidate is a non-static // method which is invoked from native and isn't picky about visibility (it'll get invoked regardless of // visibility). OnValidate is different from the other magic methods in that it only gets invoked from // the Editor. A good practice is to wrap OnValidate with #if UNITY_EDITOR so that the function can be // stripped out for deployment. // // To expand on ScriptableObject a bit. Native Unity code doesn't distinguish between MonoBehaviour and // ScriptableObject. They are the same native type (it's confusing, I know, and everyone gets tripped up // by it that looks at the native code base). The only difference is in how the object is used, // MonoBehaviours live on GameObjects, while ScriptableObjects can live alone.So in general, all magic // methods that would make sense without a GameObject context should work and be implemented for // ScriptableObjects. Off the top of my head this includes, Awake, OnEnable, OnDisable, OnDestroy, // OnValidate, and Reset, but there could be more. type = unityApi.FindType("ScriptableObject"); if (type != null) { var eventFunction = new UnityApiEventFunction("OnValidate", false, false, ApiType.Void, apiVersion, description: "This function is called when the script is loaded or a value is changed in the inspector (Called in the editor only).", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("Reset", false, false, ApiType.Void, apiVersion, description: "Reset to default values.", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); } }
public static void Main(string[] args) { if (args.Length != 1 && args.Length != 2) { Console.WriteLine("Usage: ApiParser.exe docsFolder"); Console.WriteLine(" ApiParser.exe apiXmlPath version"); Console.WriteLine(); Console.WriteLine("ApiParser.exe docsFolder"); Console.WriteLine(" Parse all documentation installed by Unity Hub, as well as everything in the docsFolder and create a new api.xml"); Console.WriteLine(); Console.WriteLine(" docsFolder - folder that contains multiple versions of Unity docs"); Console.WriteLine(" Contents should be in the format Documentation-X.Y.ZfA/Documentation/en/ScriptReference"); Console.WriteLine(); Console.WriteLine("ApiParser.exe apiXmlPath version"); Console.WriteLine(" Parse the installed documentation corresponding to version and merge into an existing api.xml file"); Console.WriteLine(); Console.WriteLine(" apiXmlPath - location of api.xml to read and merge into"); Console.WriteLine(" version - version of Unity to read docs from. Must be installed in standard Unity Hub location"); Console.WriteLine(); Console.WriteLine("Note that the output file is written to the current directory"); return; } var stopwatch = Stopwatch.StartNew(); var apiXml = FileSystemPath.Parse("api.xml"); var docVersions = new List <(string, Version)>(); if (args.Length == 1) { Directory.SetCurrentDirectory(args[0]); foreach (var directory in Directory.EnumerateDirectories(Directory.GetCurrentDirectory())) { var docFolder = Path.Combine(Directory.GetCurrentDirectory(), directory); var version = Regex.Match(directory, @"Documentation-(\d+.\d+)").Groups[1].Value; docVersions.Add((docFolder, Version.Parse(version))); } foreach (var directory in Directory.EnumerateDirectories(Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Unity", "Hub", "Editor"))) { var docFolder = GetDocumentationRoot(directory).FullPath; var version = Regex.Match(directory, @"(\d+.\d+)").Groups[1].Value; docVersions.Add((docFolder, Version.Parse(version))); } docVersions = docVersions.OrderBy(v => v.Item2).ToList(); } else { apiXml = FileSystemPath.ParseRelativelyTo(args[0], FileSystemPath.Parse(Directory.GetCurrentDirectory())); if (!apiXml.ExistsFile) { throw new InvalidOperationException("api.xml path does not exist"); } var requiredVersion = args[1]; var docRoot = GetDocumentationRoot(requiredVersion); if (!docRoot.ExistsDirectory) { throw new InvalidOperationException($"Cannot find locally installed docs: {docRoot}"); } var parseableVersion = Regex.Match(requiredVersion, @"^(\d+\.\d+)").Groups[1].Value; docVersions.Add((docRoot.FullPath, Version.Parse(parseableVersion))); } var unityApi = new UnityApi(); if (apiXml.ExistsFile) { unityApi = UnityApi.ImportFrom(apiXml); } var typeResolver = new TypeResolver(); var parser = new ApiParser(unityApi, typeResolver); foreach (var(name, version) in docVersions) { Console.WriteLine($"{name} ({version})"); parser.ParseFolder(name, version); AddUndocumentedApis(unityApi, version); } // These modify existing functions AddUndocumentedOptionalParameters(unityApi); AddUndocumentedCoroutines(unityApi); FixDataFromIncorrectDocs(unityApi, typeResolver); using (var writer = new XmlTextWriter(apiXml.FullPath, Encoding.UTF8) { Formatting = Formatting.Indented }) { parser.ExportTo(writer); } Console.WriteLine("Done. Elapsed time: {0}", stopwatch.Elapsed); // Console.WriteLine( "Press <Enter> key to continue..." ); // Console.ReadLine(); }
// Note that if we add new undocumented APIs, this won't set the correct min/max version range, and will only // apply the given api versions. That gives us two options: // 1) Recreate the api.xml file from scratch by parsing the documentation of every Unity version since 5.0 // 2) Cheat a little. When incrementally updating an existing api.xml for a single version and also adding new // undocumented APIs, add extra calls to AddUndocumentedApis with the min/max version for those new APIs. // Don't check these extra calls in! private static void AddUndocumentedApis(UnityApi unityApi, Version apiVersion) { // From AssetPostprocessingInternal var type = unityApi.FindType("AssetPostprocessor"); if (type != null) { var eventFunction = new UnityApiEventFunction("OnPreprocessAssembly", false, false, ApiType.Void, apiVersion, undocumented: true); eventFunction.AddParameter("pathName", ApiType.String); type.MergeEventFunction(eventFunction, apiVersion); // From GitHub. Love the optimism in this one :) // https://github.com/Unity-Technologies/UnityCsReference/blob/96187e5fc1a23847206bf66b6f2d0e4a1ad43301/Editor/Mono/AssetPostprocessor.cs#L96 var description = "This is undocumented, and a 'safeguard' for when Visual Studio gets a new release that " + "is incompatible with Unity, so that users can postprocess our csproj files to fix the issue (or " + "just completely replace them). Hopefully we'll never need this."; eventFunction = new UnityApiEventFunction("OnGeneratedCSProjectFiles", true, false, ApiType.Void, apiVersion, description, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // Technically, return type is optional // https://github.com/Unity-Technologies/UnityCsReference/blob/96187e5fc1a23847206bf66b6f2d0e4a1ad43301/Editor/Mono/AssetPostprocessor.cs#L138 description = "This callback is used by UnityVS to take over project generation from Unity"; eventFunction = new UnityApiEventFunction("OnPreGeneratingCSProjectFiles", true, false, ApiType.Bool, apiVersion, description, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // These two were added in 2018.1, as verified on GitHub // https://github.com/Unity-Technologies/UnityCsReference/blob/2017.4/Editor/Mono/AssetPostprocessor.cs // https://github.com/Unity-Technologies/UnityCsReference/blob/2018.1/Editor/Mono/AssetPostprocessor.cs#L76 if (apiVersion >= new Version(2018, 1)) { // Technically, return type is optional // https://github.com/Unity-Technologies/UnityCsReference/blob/96187e5fc1a23847206bf66b6f2d0e4a1ad43301/Editor/Mono/AssetPostprocessor.cs#L123 description = "This callback is used by C# code editors to modify the .csproj files."; eventFunction = new UnityApiEventFunction("OnGeneratedCSProject", true, false, ApiType.String, apiVersion, description, undocumented: true); eventFunction.AddParameter("path", ApiType.String); eventFunction.AddParameter("content", ApiType.String); type.MergeEventFunction(eventFunction, apiVersion); // Technically, return type is optional // https://github.com/Unity-Technologies/UnityCsReference/blob/96187e5fc1a23847206bf66b6f2d0e4a1ad43301/Editor/Mono/AssetPostprocessor.cs#L108 description = "This callback is used by C# code editors to modify the .sln file"; eventFunction = new UnityApiEventFunction("OnGeneratedSlnSolution", true, false, ApiType.String, apiVersion, description, undocumented: true); eventFunction.AddParameter("path", ApiType.String); eventFunction.AddParameter("content", ApiType.String); type.MergeEventFunction(eventFunction, apiVersion); } } // From AssetModificationProcessorInternal type = unityApi.FindType("AssetModificationProcessor"); if (type != null) { var eventFunction = new UnityApiEventFunction("OnStatusUpdated", true, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); } type = unityApi.FindType("MonoBehaviour"); if (type != null) { const string description = "This callback is called if an associated RectTransform has its dimensions changed."; var eventFunction = new UnityApiEventFunction("OnRectTransformDimensionsChange", false, false, ApiType.Void, apiVersion, description, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("OnBeforeTransformParentChanged", false, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("OnDidApplyAnimationProperties", false, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("OnCanvasGroupChanged", false, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); eventFunction = new UnityApiEventFunction("OnCanvasHierarchyChanged", false, false, ApiType.Void, apiVersion, undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); } // ScriptableObject // From Shawn White @ Unity (https://github.com/JetBrains/resharper-unity/issues/79#issuecomment-266727851): // OnValidate's behavior on ScriptableObject is the same as on MonoBehaviour. OnValidate is a non-static // method which is invoked from native and isn't picky about visibility (it'll get invoked regardless of // visibility). OnValidate is different from the other magic methods in that it only gets invoked from // the Editor. A good practice is to wrap OnValidate with #if UNITY_EDITOR so that the function can be // stripped out for deployment. // // To expand on ScriptableObject a bit. Native Unity code doesn't distinguish between MonoBehaviour and // ScriptableObject. They are the same native type (it's confusing, I know, and everyone gets tripped up // by it that looks at the native code base). The only difference is in how the object is used, // MonoBehaviours live on GameObjects, while ScriptableObjects can live alone.So in general, all magic // methods that would make sense without a GameObject context should work and be implemented for // ScriptableObjects. Off the top of my head this includes, Awake, OnEnable, OnDisable, OnDestroy, // OnValidate, and Reset, but there could be more. type = unityApi.FindType("ScriptableObject"); if (type != null && apiVersion < new Version(2020, 1)) { // Documented in 2020.1 var eventFunction = new UnityApiEventFunction("OnValidate", false, false, ApiType.Void, apiVersion, description: "This function is called when the script is loaded or a value is changed in the inspector (Called in the editor only).", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // Documented in 2020.1 eventFunction = new UnityApiEventFunction("Reset", false, false, ApiType.Void, apiVersion, description: "Reset to default values.", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); } // TODO: Check if these event functions are available in 5.0 - 5.6 type = unityApi.FindType("Editor"); if (type != null && apiVersion >= new Version(2017, 1)) { // Editor.OnPreSceneGUI has been around since at least 2017.1. Still undocumented as of 2020.2 // https://github.com/Unity-Technologies/UnityCsReference/blob/2017.1/Editor/Mono/SceneView/SceneView.cs#L2436 var eventFunction = new UnityApiEventFunction("OnPreSceneGUI", false, false, ApiType.Void, apiVersion, description: "Called before the Scene view is drawn.", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // Editor.OnSceneDrag has been around since at least 2017.1. Still undocumented as of 2020.2 // https://github.com/Unity-Technologies/UnityCsReference/blob/2017.1/Editor/Mono/GUI/EditorCache.cs#L63 eventFunction = new UnityApiEventFunction("OnSceneDrag", false, false, ApiType.Void, apiVersion, description: "Called for each object dragged onto the scene view", undocumented: true); eventFunction.AddParameter("sceneView", new ApiType("UnityEditor.SceneView"), "The current scene view"); eventFunction.AddParameter("index", ApiType.Int, "The index into the DragAndDrop.objectReferences array"); type.MergeEventFunction(eventFunction, apiVersion); if (apiVersion < new Version(2020, 2)) { // Editor.HasFrameBounds has been around since at least 2017.1. First documented in 2020.2 // https://github.com/Unity-Technologies/UnityCsReference/blob/2017.1/Editor/Mono/SceneView/SceneView.cs#L2296 // https://docs.unity3d.com/2020.2/Documentation/ScriptReference/Editor.HasFrameBounds.html eventFunction = new UnityApiEventFunction("HasFrameBounds", false, false, ApiType.Bool, apiVersion, description: "Validates whether custom bounds can be calculated for this editor.", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // Editor.OnGetFrameBounds has been around since at least 2017.1. First documented in 2020.2 // https://github.com/Unity-Technologies/UnityCsReference/blob/2017.1/Editor/Mono/SceneView/SceneView.cs#L2303 // https://docs.unity3d.com/2020.2/Documentation/ScriptReference/Editor.OnGetFrameBounds.html eventFunction = new UnityApiEventFunction("OnGetFrameBounds", false, false, new ApiType("UnityEngine.Bounds"), apiVersion, description: "Gets custom bounds for the target of this editor.", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); } } // TODO: Check if these event functions are available in 5.0 - 5.6 type = unityApi.FindType("EditorWindow"); if (type != null && apiVersion >= new Version(2017, 1)) { // EditorWindow.ModifierKeysChanged has been around since at least 2017.1. Still undocumented as of 2020.2 // https://github.com/Unity-Technologies/UnityCsReference/blob/2017.1/Editor/Mono/HostView.cs#L290 // http://www.improck.com/2014/11/editorwindow-modifier-keys/ var eventFunction = new UnityApiEventFunction("ModifierKeysChanged", false, false, ApiType.Void, apiVersion, description: "Called when the modifier keys are changed. Automatically registers and de-registers the EditorApplication.modifierKeysChanged event", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // EditorWindow.ShowButton has been around since at least 2017.1. Still undocumented as of 2020.2 // https://github.com/Unity-Technologies/UnityCsReference/blob/2017.1/Editor/Mono/HostView.cs#L356 // http://www.improck.com/2014/11/editorwindow-inspector-lock-icon/ eventFunction = new UnityApiEventFunction("ShowButton", false, false, ApiType.Void, apiVersion, description: "Allow Editor panes to show a small button next to the generic menu (e.g. inspector lock icon)", undocumented: true); eventFunction.AddParameter("rect", new ApiType("UnityEngine.Rect"), "Position to draw the button"); type.MergeEventFunction(eventFunction, apiVersion); // EditorWindow.OnBecameVisible has been around since at least 2017.1. Still undocumented as of 2020.2 // https://github.com/Unity-Technologies/UnityCsReference/blob/2017.1/Editor/Mono/HostView.cs#L302 eventFunction = new UnityApiEventFunction("OnBecameVisible", false, false, ApiType.Void, apiVersion, description: "Called when an editor window has been opened", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // EditorWindow.OnBecameInvisible has been around since at least 2017.1. Still undocumented as of 2020.2 // https://github.com/Unity-Technologies/UnityCsReference/blob/2017.1/Editor/Mono/HostView.cs#L337 eventFunction = new UnityApiEventFunction("OnBecameInvisible", false, false, ApiType.Void, apiVersion, description: "Called when an editor window has been closed", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // EditorWindow.OnDidOpenScene has been around since at least 2017.1. Still undocumented as of 2020.2 // https://github.com/Unity-Technologies/UnityCsReference/blob/2017.1/Editor/Mono/HostView.cs#L163 eventFunction = new UnityApiEventFunction("OnDidOpenScene", false, false, ApiType.Void, apiVersion, description: "Called when a scene has been opened", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); if (apiVersion >= new Version(2019, 1)) { // EditorWindow.OnAddedAsTab was introduced in 2019.1. Still undocumented as of 2020.2 // https://github.com/Unity-Technologies/UnityCsReference/blob/2019.1/Editor/Mono/GUI/DockArea.cs#L188 eventFunction = new UnityApiEventFunction("OnAddedAsTab", false, false, ApiType.Void, apiVersion, description: "Called when the editor window is added as a tab", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); // EditorWindow.OnBeforeRemovedAsTab was introduced in 2019.1 // https://github.com/Unity-Technologies/UnityCsReference/blob/2019.1/Editor/Mono/GUI/DockArea.cs#L195 eventFunction = new UnityApiEventFunction("OnBeforeRemovedAsTab", false, false, ApiType.Void, apiVersion, description: "Called before an editor window is removed as a tab", undocumented: true); } if (apiVersion >= new Version(2019, 3)) { // EditorWindow.OnTabDetached was introduced in 2019.3 // https://github.com/Unity-Technologies/UnityCsReference/blob/2019.3/Editor/Mono/GUI/DockArea.cs#L940 eventFunction = new UnityApiEventFunction("OnTabDetached", false, false, ApiType.Void, apiVersion, description: "Called during drag and drop, when an editor window tab is detached", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); } if (apiVersion >= new Version(2020, 1)) { // EditorWindow.OnMainWindowMove was introduced in 2020.1 // https://github.com/Unity-Technologies/UnityCsReference/blob/2020.1/Editor/Mono/HostView.cs#L343 // See comment here // https://github.com/Unity-Technologies/UnityCsReference/blob/2020.1/Editor/Mono/ExternalPlayModeView/ExternalPlayModeView.cs#L112 eventFunction = new UnityApiEventFunction("OnMainWindowMove", false, false, ApiType.Void, apiVersion, description: "Called when the main window is moved", undocumented: true); type.MergeEventFunction(eventFunction, apiVersion); } } }