public static void BackupAssetsFolder(string backupLabel) { backupLabel = PathUtility.MakeSafeFilename(backupLabel, '_'); PathUtility.CreateDirectoryIfNeeded(Paths.backups); var fileName = $"Assets_{backupLabel}.zip"; var addEntryIndex = 0; var saveEntryIndex = 0; using (var zip = new ZipFile()) { zip.UseZip64WhenSaving = Zip64Option.AsNecessary; zip.AddProgress += (sender, e) => { EditorUtility.DisplayProgressBar("Creating Backup...", e.CurrentEntry != null ? e.CurrentEntry.FileName : "...", (float)(addEntryIndex++) / e.EntriesTotal); }; zip.SaveProgress += (sender, e) => { EditorUtility.DisplayProgressBar("Creating Backup...", e.CurrentEntry != null ? e.CurrentEntry.FileName : "...", (float)(saveEntryIndex++) / e.EntriesTotal); }; List <string> listOfAssets = Find <LudiqScriptableObject>(); foreach (string assetPath in listOfAssets) { zip.AddFile(assetPath); } var zipPath = Path.Combine(Paths.backups, fileName); VersionControlUtility.Unlock(zipPath); zip.Save(zipPath); EditorUtility.ClearProgressBar(); } }
// Automatically generates the link.xml file to prevent stripping. // Currently only used for plugin assemblies, because blanket preserving // all setting assemblies sometimes causes the IL2CPP process to fail. // For settings assemblies, the AOT stubs are good enough to fool // the static code analysis without needing this full coverage. // https://docs.unity3d.com/Manual/iphone-playerSizeOptimization.html // However, for FullSerializer, we need to preserve our custom assemblies. // This is mostly because IL2CPP will attempt to transform non-public // property setters used in deserialization into read-only accessors // that return false on PropertyInfo.CanWrite, but only in stripped builds. // Therefore, in stripped builds, FS will skip properties that should be // deserialized without any error (and that took hours of debugging to figure out). private void GenerateLinker() { var linker = new XDocument(); var linkerNode = new XElement("linker"); if (!PluginContainer.initialized) { PluginContainer.Initialize(); } foreach (var pluginAssembly in PluginContainer.plugins .SelectMany(plugin => plugin.GetType() .GetAttributes <PluginRuntimeAssemblyAttribute>() .Select(a => a.assemblyName)) .Distinct()) { var assemblyNode = new XElement("assembly"); var fullnameAttribute = new XAttribute("fullname", pluginAssembly); var preserveAttribute = new XAttribute("preserve", "all"); assemblyNode.Add(fullnameAttribute); assemblyNode.Add(preserveAttribute); linkerNode.Add(assemblyNode); } linker.Add(linkerNode); PathUtility.CreateDirectoryIfNeeded(BoltCore.Paths.transientGenerated); PathUtility.DeleteProjectFileIfExists(linkerPath, true); // Using ToString instead of Save to omit the <?xml> declaration, // which doesn't appear in the Unity documentation page for the linker. File.WriteAllText(linkerPath, linker.ToString()); }
public static void ExportAllEditorIcon() { var assetBundle = typeof(EditorGUIUtility).GetMethod("GetEditorAssetBundle", BindingFlags.Static | BindingFlags.NonPublic) .Invoke(null, null) as AssetBundle; var outputFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "EditorTextures"); PathUtility.CreateDirectoryIfNeeded(outputFolder); var textures = assetBundle.LoadAllAssets <Texture2D>(); try { for (int i = 0; i < textures.Length; i++) { var texture = textures[i]; try { ProgressUtility.DisplayProgressBar("Export Editor Textures", texture.name, (float)i / textures.Length); var outputPath = Path.Combine(outputFolder, texture.name + ".png"); File.WriteAllBytes(outputPath, CreateReadableCopy(texture).EncodeToPNG()); } catch (Exception ex) { Debug.LogError($"Failed to export {texture.name}:\n{ex}"); } } } finally { ProgressUtility.ClearProgressBar(); } }
public void GenerateProviderScripts() { if (Directory.Exists(BoltCore.Paths.propertyProviders)) { foreach (var file in Directory.GetFiles(BoltCore.Paths.propertyProviders)) { File.Delete(file); } } if (Directory.Exists(BoltCore.Paths.propertyProvidersEditor)) { foreach (var file in Directory.GetFiles(BoltCore.Paths.propertyProvidersEditor)) { File.Delete(file); } } PathUtility.CreateDirectoryIfNeeded(BoltCore.Paths.propertyProviders); PathUtility.CreateDirectoryIfNeeded(BoltCore.Paths.propertyProvidersEditor); foreach (var type in typeset.Where(SerializedPropertyUtility.HasCustomDrawer)) { var directory = Codebase.IsEditorType(type) ? BoltCore.Paths.propertyProvidersEditor : BoltCore.Paths.propertyProviders; var path = Path.Combine(directory, GetProviderScriptName(type) + ".cs"); VersionControlUtility.Unlock(path); File.WriteAllText(path, GenerateProviderSource(type)); } AssetDatabase.Refresh(); }
private void GenerateStubScript(string scriptFilePath) { var scriptDirectory = Path.GetDirectoryName(scriptFilePath); PathUtility.CreateDirectoryIfNeeded(scriptDirectory); PathUtility.DeleteProjectFileIfExists(scriptFilePath, true); using (var scriptWriter = new StreamWriter(scriptFilePath)) { FindAndWriteAotStubs(scriptWriter); } AssetDatabase.Refresh(); }
public void OnGUI() { GUILayout.Space(5f); GUILayout.Label(Title, EditorStyles.boldLabel); GUILayout.Space(5f); if (GUILayout.Button(ButtonBackupLabel, Styles.defaultsButton)) { VSBackupUtility.Backup(); EditorUtility.DisplayDialog("Backup", "Backup completed successfully.", "OK"); } if (GUILayout.Button(ButtonRestoreLabel, Styles.defaultsButton)) { PathUtility.CreateDirectoryIfNeeded(Paths.backups); Process.Start(Paths.backups); } }
public static string GenerateDocumentation(string projectPath) { PathUtility.CreateDirectoryIfNeeded(BoltCore.Paths.assemblyDocumentations); var projectName = Path.GetFileNameWithoutExtension(projectPath); if (!File.Exists(projectPath)) { throw new FileNotFoundException($"Project file not found: '{projectPath}'."); } var projectBuilderPath = Paths.projectBuilder; if (!File.Exists(projectBuilderPath)) { throw new FileNotFoundException($"Project builder not found: '{projectBuilderPath}'.\nYou can download the latest MSBuild from: {Paths.MsBuildDownloadLink}"); } using (var process = new Process()) { var projectXml = XDocument.Load(projectPath); var projectRootNamespace = projectXml.Root.GetDefaultNamespace(); var assemblyName = projectXml.Descendants(projectRootNamespace + "AssemblyName").Single().Value; var documentationPath = Path.Combine(BoltCore.Paths.assemblyDocumentations, assemblyName + ".xml"); process.StartInfo = new ProcessStartInfo(); process.StartInfo.FileName = projectBuilderPath; process.StartInfo.Arguments = "/p:Configuration=Debug " + "/p:GenerateDocumentation=true " + "/p:WarningLevel=0 " + $"/p:DocumentationFile=\"{documentationPath}\" " + $"\"{projectPath}\""; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.StartInfo.CreateNoWindow = true; process.StartInfo.UseShellExecute = false; var timeout = 20000; var output = new StringBuilder(); var error = new StringBuilder(); using (var outputWaitHandle = new AutoResetEvent(false)) using (var errorWaitHandle = new AutoResetEvent(false)) { process.OutputDataReceived += (sender, e) => { if (e.Data == null) { outputWaitHandle.Set(); } else { output.AppendLine(e.Data); } }; process.ErrorDataReceived += (sender, e) => { if (e.Data == null) { errorWaitHandle.Set(); } else { error.AppendLine(e.Data); } }; process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); if (process.WaitForExit(timeout) && outputWaitHandle.WaitOne(timeout) && errorWaitHandle.WaitOne(timeout)) { if (process.ExitCode != 0) { throw new BuildFailedException($"Failed to build project '{projectName}':\n{process.StartInfo.Arguments}\n{error}\n{output}"); } XmlDocumentation.ClearCache(); return(output.ToString()); } else { throw new TimeoutException("Build process timed out."); } } } }
private void GenerateStubScript(string scriptPath, IEnumerable <AotStubWriter> stubWriters) { Ensure.That(nameof(stubWriters)).IsNotNull(stubWriters); var unit = new CodeCompileUnit(); var @namespace = new CodeNamespace("Unity.VisualScripting.Generated.Aot"); unit.Namespaces.Add(@namespace); var @class = new CodeTypeDeclaration("AotStubs") { IsClass = true }; @class.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(PreserveAttribute)))); @namespace.Types.Add(@class); var usedMethodNames = new HashSet <string>(); foreach (var stubWriter in stubWriters.OrderBy(sw => sw.stubMethodComment)) { if (stubWriter.skip) { continue; } var methodName = stubWriter.stubMethodName; var i = 0; while (usedMethodNames.Contains(methodName)) { methodName = stubWriter.stubMethodName + "_" + i++; } usedMethodNames.Add(methodName); @class.Comments.Add(new CodeCommentStatement(stubWriter.stubMethodComment)); var @method = new CodeMemberMethod { Name = methodName, ReturnType = new CodeTypeReference(typeof(void)), Attributes = MemberAttributes.Public | MemberAttributes.Static }; @method.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(PreserveAttribute), CodeTypeReferenceOptions.GlobalReference))); @method.Comments.Add(new CodeCommentStatement(stubWriter.stubMethodComment)); @method.Statements.AddRange(stubWriter.GetStubStatements().ToArray()); @class.Members.Add(@method); } PathUtility.CreateDirectoryIfNeeded(BoltCore.Paths.transientGenerated); PathUtility.DeleteProjectFileIfExists(aotStubsPath, true); using (var provider = CodeDomProvider.CreateProvider("CSharp")) { var options = new CodeGeneratorOptions { BracingStyle = "C", IndentString = "\t", BlankLinesBetweenMembers = true, ElseOnClosing = false, VerbatimOrder = true }; using (var scriptWriter = new StreamWriter(scriptPath)) { provider.GenerateCodeFromCompileUnit(new CodeSnippetCompileUnit("#pragma warning disable 219"), scriptWriter, options); // Disable unused variable warning provider.GenerateCodeFromCompileUnit(unit, scriptWriter, options); } } AssetDatabase.Refresh(); }