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();
            }
        }
Пример #2
0
        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();
            }
        }
Пример #3
0
        // 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();
        }
Пример #5
0
 public static void ShowBackupFolder()
 {
     PathUtility.CreateDirectoryIfNeeded(Paths.backups);
     Process.Start(Paths.backups);
 }
Пример #6
0
        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.");
                        }
                    }
            }
        }
Пример #7
0
        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();
        }
Пример #8
0
        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();
        }