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 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); }; zip.AddDirectory(Paths.assets); 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). public static void GenerateLinker() { var linker = new XDocument(); var linkerNode = new XElement("linker"); 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(LudiqCore.Paths.transientGenerated); DeleteLinker(); // 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 void GenerateProviderScripts() { if (Directory.Exists(LudiqCore.Paths.propertyProviders)) { foreach (var file in Directory.GetFiles(LudiqCore.Paths.propertyProviders)) { File.Delete(file); } } if (Directory.Exists(LudiqCore.Paths.propertyProvidersEditor)) { foreach (var file in Directory.GetFiles(LudiqCore.Paths.propertyProvidersEditor)) { File.Delete(file); } } PathUtility.CreateDirectoryIfNeeded(LudiqCore.Paths.propertyProviders); PathUtility.CreateDirectoryIfNeeded(LudiqCore.Paths.propertyProvidersEditor); foreach (var type in typeset.Where(SerializedPropertyUtility.HasCustomDrawer)) { var directory = Codebase.IsEditorType(type) ? LudiqCore.Paths.propertyProvidersEditor : LudiqCore.Paths.propertyProviders; var path = Path.Combine(directory, GetProviderScriptName(type) + ".cs"); VersionControlUtility.Unlock(path); File.WriteAllText(path, GenerateProviderSource(type)); } AssetDatabase.Refresh(); }
public static void ShowBackupFolder() { PathUtility.CreateDirectoryIfNeeded(Paths.backups); Process.Start(Paths.backups); }
public static string GenerateDocumentation(string projectPath) { PathUtility.CreateDirectoryIfNeeded(LudiqCore.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(LudiqCore.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."); } } } }
protected override void OnContentGUI() { if (!plugins.Any()) { Complete(); } GUILayout.BeginVertical(Styles.background, GUILayout.ExpandHeight(true)); LudiqGUI.FlexibleSpace(); GUILayout.Label($"The following plugins have been downgraded to a previous version: ", LudiqStyles.centeredLabel); LudiqGUI.FlexibleSpace(); UpdateWizard.DrawPluginVersionTable(plugins); LudiqGUI.FlexibleSpace(); GUILayout.Label("This will likely cause backwards incompatibility issues.", LudiqStyles.centeredLabel); GUILayout.Label("We recommend that you re-install their saved version to avoid data corruption.", LudiqStyles.centeredLabel); LudiqGUI.FlexibleSpace(); LudiqGUI.BeginHorizontal(); LudiqGUI.FlexibleSpace(); if (GUILayout.Button("Close", Styles.button)) { throw new WindowClose(); } LudiqGUI.Space(10); if (GUILayout.Button("Force Consolidate", Styles.button)) { var consolidationExplanation = string.Empty; consolidationExplanation += $"By forcing consolidation, the saved versions will be set to match the installed versions. "; consolidationExplanation += "This does not roll back updates and may lead to data corruption. "; consolidationExplanation += "You should only do this if you know what you are doing. "; consolidationExplanation += "A backup will be created automatically if you decide to proceed."; if (EditorUtility.DisplayDialog("Force Consolidate Version", consolidationExplanation, "Force Consolidate", "Cancel")) { var forceConsolidate = false; if (EditorUtility.DisplayDialog("Force Consolidate Version", "Create backup before consolidating?", "Yes", "No")) { try { BackupUtility.BackupAssetsFolder(); forceConsolidate = true; } catch (Exception ex) { EditorUtility.DisplayDialog("Backup", "Failed to create backup. Version consolidation canceled.", "OK"); UnityEngine.Debug.LogException(ex); } } else { forceConsolidate = true; } if (forceConsolidate) { foreach (var plugin in plugins) { plugin.manifest.savedVersion = plugin.manifest.currentVersion; } Complete(); } } } LudiqGUI.Space(10); if (GUILayout.Button("Backups", Styles.button)) { PathUtility.CreateDirectoryIfNeeded(Paths.backups); Process.Start(Paths.backups); } LudiqGUI.FlexibleSpace(); LudiqGUI.EndHorizontal(); LudiqGUI.FlexibleSpace(); LudiqGUI.EndVertical(); }
private static void GenerateStubScript(string scriptPath, IEnumerable <AotStubWriter> stubWriters) { Ensure.That(nameof(stubWriters)).IsNotNull(stubWriters); var unit = new CodeCompileUnit(); var @namespace = new CodeNamespace("Ludiq.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(LudiqCore.Paths.transientGenerated); DeleteStubScript(); 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(); }