Esempio n. 1
0
        public override void OnInspectorGUI()
        {
            DrawPropertiesExcluding(serializedObject, "m_Script", nameof(ThunderstoreManifest.dependencies));

            var property = serializedObject.FindProperty(nameof(ThunderstoreManifest.dependencies));

            var thunderManifest = serializedObject.targetObject as ThunderstoreManifest;
            var manifest        = AssetDatabase.LoadAssetAtPath <Manifest>(AssetDatabase.GetAssetPath(thunderManifest));

            if (thunderManifest)
            {
                using (new VerticalScope(GUI.skin.box))
                {
                    Label("Dependencies");
                    for (int i = 0; i < thunderManifest.dependencies.Count; i++)
                    {
                        var depName = thunderManifest.dependencies[i];

                        Label(depName);

                        var bp = GUILayoutUtility.GetLastRect();
                        bp = new Rect(bp.width + 4, bp.y + 1, 13, bp.height - 2);
                        if (Event.current.type == EventType.Repaint)
                        {
                            GUI.skin.box.Draw(bp, new GUIContent(""), 0);
                            GUIContent content     = new GUIContent("x");
                            var        contentSize = GUIStyle.none.CalcSize(content);
                            GUIStyle.none.Draw(new Rect(bp.x + 3, bp.y - 1, bp.width, bp.height), content, 0);
                        }
                        if (Event.current.type == EventType.MouseUp && bp.Contains(Event.current.mousePosition))
                        {
                            var dependencyPath = Path.Combine(Packages, depName);

                            if (Directory.Exists(dependencyPath))
                            {
                                Directory.Delete(dependencyPath, true);
                            }

                            var listed = thunderManifest.dependencies.ToList();
                            listed.RemoveAt(i);
                            thunderManifest.dependencies = new DependencyList(listed);

                            property.serializedObject.SetIsDifferentCacheDirty();

                            property.serializedObject.ApplyModifiedProperties();

                            AssetDatabase.Refresh();
                        }
                    }

                    var suggestRect = GUILayoutUtility.GetRect(currentViewWidth, singleLineHeight);
                    suggestRect.x++;
                    suggestRect.width -= 4;

                    suggestor.OnSuggestionGUI = RenderSuggestion;
                    suggestor.OnSuggestGUI(suggestRect, "Dependency Search");
                    Space(2);
                }
            }

            switch (Event.current.type)
            {
            case EventType.Repaint:
                dragDropRect = GUILayoutUtility.GetLastRect();
                break;

            case EventType.DragUpdated:
                if (!dragDropRect.Contains(Event.current.mousePosition))
                {
                    break;
                }

                if (DragAndDrop.objectReferences.OfType <Manifest>().Any())
                {
                    var canDrop   = false;
                    var manifests = DragAndDrop.objectReferences.OfType <Manifest>().ToArray();

                    foreach (var droppedManifest in manifests)
                    {
                        foreach (var depThunderManifest in droppedManifest.Data.OfType <ThunderstoreManifest>())
                        {
                            string thisGuid = $"{thunderManifest.author}-{manifest.name}";
                            if (!depThunderManifest.dependencies.Any(dp => dp.StartsWith(thisGuid)) &&
                                !thisGuid.StartsWith($"{depThunderManifest.author}-{droppedManifest.name}"))
                            {
                                canDrop = true;
                                break;
                            }
                            if (canDrop)
                            {
                                break;
                            }
                        }
                    }
                    if (canDrop)
                    {
                        DragAndDrop.visualMode = DragAndDropVisualMode.Link;
                        Event.current.Use();
                        return;
                    }
                }
                if (DragAndDrop.paths.Any(path => Path.GetExtension(path).Equals(".zip")))
                {
                    var canDrop = false;
                    foreach (var path in DragAndDrop.paths.Where(path => Path.GetExtension(path).Equals(".zip")))
                    {
                        using (var archive = new ZipArchive(File.OpenRead(path)))
                        {
                            foreach (var entry in archive.Entries)
                            {
                                if (!"manifest.json".Equals(Path.GetFileName(entry.FullName), System.StringComparison.OrdinalIgnoreCase))
                                {
                                    continue;
                                }
                                canDrop = true;
                                break;
                            }
                        }
                    }

                    if (canDrop)
                    {
                        DragAndDrop.visualMode = DragAndDropVisualMode.Link;
                        Event.current.Use();
                        return;
                    }
                }
                break;

            case EventType.DragPerform:
                if (DragAndDrop.objectReferences.OfType <Manifest>().Any())
                {
                    //Debug.Log("Dropping Manifests");
                    var manifests = DragAndDrop.objectReferences.OfType <Manifest>();
                    foreach (var droppedManifest in manifests)
                    {
                        foreach (var dependence in droppedManifest.Data.OfType <ThunderstoreManifest>())
                        {
                            string dependency = $"{dependence.author}-{droppedManifest.name}-{dependence.versionNumber}";
                            if (thunderManifest.dependencies.Any(dp => dp.StartsWith($"{dependence.author}-{droppedManifest.name}")))
                            {
                                thunderManifest.dependencies.RemoveAll(dp => dp.StartsWith($"{dependence.author}-{droppedManifest.name}"));
                            }

                            if (thunderManifest.dependencies == null || !thunderManifest.dependencies.Any())
                            {
                                thunderManifest.dependencies = new DependencyList();
                            }

                            thunderManifest.dependencies.Add(dependency);
                            property.serializedObject.SetIsDifferentCacheDirty();
                            property.serializedObject.ApplyModifiedProperties();
                            DragAndDrop.AcceptDrag();
                            Event.current.Use();
                            return;
                        }
                    }
                }
                if (DragAndDrop.paths.Any(path => Path.GetExtension(path).Equals(".zip")))
                {
                    bool refresh = false;
                    foreach (var path in DragAndDrop.paths.Where(path => Path.GetExtension(path).Equals(".zip")))
                    {
                        using (var archive = new ZipArchive(File.OpenRead(path)))
                        {
                            var entry = archive.Entries.FirstOrDefault(e => "manifest.json".Equals(Path.GetFileName(e.FullName), System.StringComparison.OrdinalIgnoreCase));
                            if (entry == null)
                            {
                                continue;
                            }

                            var archiveName = Path.GetFileNameWithoutExtension(path);
                            var outputDir   = Path.Combine("Packages", archiveName);
                            refresh = true;

                            Directory.CreateDirectory(outputDir);
                            archive.ExtractToDirectory(outputDir);

                            foreach (var assemblyPath in Directory.EnumerateFiles(outputDir, "*.dll", SearchOption.AllDirectories))
                            {
                                PackageHelper.WriteAssemblyMetaData(assemblyPath, $"{assemblyPath}.meta");
                            }

                            using (var reader = new StreamReader(entry.Open()))
                            {
                                var    stubManifest = JsonUtility.FromJson <ThunderstoreManifestStub>(reader.ReadToEnd());
                                string author       = stubManifest.author ?? archiveName.Substring(0, archiveName.IndexOf('-'));
                                string guid         = $"{author}-{stubManifest.name}-{stubManifest.version_number}";
                                Debug.Log($"Added {guid} to {manifest.name} dependencies");
                                thunderManifest.dependencies.Add(guid);
                                PackageHelper.GeneratePackageManifest(
                                    stubManifest.name.ToLower(), outputDir,
                                    stubManifest.name, author,
                                    stubManifest.version_number,
                                    stubManifest.description,
                                    stubManifest.website_url);
                            }
                        }
                    }
                    if (refresh)
                    {
                        AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
                    }
                }
                break;
            }

            bool RenderSuggestion(int arg1, Package package)
            {
                if (thunderManifest.dependencies.Contains(package.latest.full_name))
                {
                    return(false);
                }

                if (Button(package.name))
                {
                    thunderManifest.dependencies.Add(package.latest.full_name);
                    property.serializedObject.SetIsDifferentCacheDirty();
                    property.serializedObject.ApplyModifiedProperties();
                    suggestor.Cleanup();

                    if (!Directory.Exists(TempDir))
                    {
                        Directory.CreateDirectory(TempDir);
                    }

                    var packages = RecurseDependencies(thunderManifest.dependencies)
                                   .GroupBy(dep => dep.latest.full_name).Select(g => g.First()).ToArray();

                    foreach (var pack in packages)
                    {
                        ThunderstoreAPI.DownloadPackage(pack, Path.Combine(TempDir, GetZipFileName(pack)));
                    }

                    return(true);
                }

                return(false);
            }
        }
Esempio n. 2
0
        public void InstallPackage(PackageGroup group, string version)
        {
            if (EditorApplication.isCompiling)
            {
                return;
            }
            var package = group[version];

            var installSet = EnumerateDependencies(package).Where(dep => !dep.group.Installed).ToArray();
            var progress   = 0.01f;
            var stepSize   = 0.33f / installSet.Length;

            //Wait till all files are put in place to load new assemblies to make installation more consistent and faster
            EditorApplication.LockReloadAssemblies();
            try
            {
                EditorUtility.DisplayProgressBar("Creating Packages", $"{installSet.Length} packages", progress);
                foreach (var installable in installSet)
                {
                    //This will cause repeated installation of dependencies
                    string packageDirectory = installable.group.InstallDirectory;

                    if (Directory.Exists(packageDirectory))
                    {
                        Directory.Delete(packageDirectory, true);
                    }
                    Directory.CreateDirectory(packageDirectory);

                    EditorUtility.DisplayProgressBar("Creating Packages", $"Creating package.json for {installable.group.PackageName}", progress += stepSize / 2);
                    PackageHelper.GeneratePackageManifest(
                        installable.group.DependencyId.ToLower(), installable.group.InstallDirectory,
                        installable.group.PackageName, installable.group.Author,
                        installable.version,
                        installable.group.Description);
                }

                AssetDatabase.SaveAssets();
                try
                {
                    //Refresh here to update the AssetDatabase so that it can manage the creation of Manifests in the packages via the Unity Package path notation
                    //e.g Packages/com.passivepicasso.thunderkit/Editor
                    AssetDatabase.Refresh();
                }
                catch { }

                EditorUtility.DisplayProgressBar("Creating Package Manifests", $"Creating {installSet.Length} manifests", progress);
                foreach (var installable in installSet)
                {
                    var installableGroup = installable.group;
                    var manifestPath     = PathExtensions.Combine(installableGroup.PackageDirectory, $"{installableGroup.PackageName}.asset");
                    if (AssetDatabase.LoadAssetAtPath <Manifest>(manifestPath))
                    {
                        AssetDatabase.DeleteAsset(manifestPath);
                    }

                    EditorUtility.DisplayProgressBar("Creating Package Manifests", $"Creating manifest for {installable.group.PackageName}", progress += stepSize);

                    var manifest = ScriptableObject.CreateInstance <Manifest>();
                    AssetDatabase.CreateAsset(manifest, manifestPath);
                    PackageHelper.WriteAssetMetaData(manifestPath);
                    AssetDatabase.Refresh();

                    manifest = AssetDatabase.LoadAssetAtPath <Manifest>(manifestPath);
                    var identity = ScriptableObject.CreateInstance <ManifestIdentity>();
                    identity.name        = nameof(ManifestIdentity);
                    identity.Author      = installableGroup.Author;
                    identity.Description = installableGroup.Description;
                    identity.Name        = installableGroup.PackageName;
                    identity.Version     = version;
                    manifest.InsertElement(identity, 0);
                    manifest.Identity = identity;
                }
                //Refresh here to update the AssetDatabase's representation of the Assets with ThunderKit managed Meta files
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();

                EditorUtility.DisplayProgressBar("Defining Package Dependencies", $"Assigning dependencies for {installSet.Length} manifests", progress);
                foreach (var installable in installSet)
                {
                    var manifestPath        = PathExtensions.Combine(installable.group.PackageDirectory, $"{installable.group.PackageName}.asset");
                    var installableManifest = AssetDatabase.LoadAssetAtPath <Manifest>(manifestPath);
                    var identity            = installableManifest.Identity;
                    EditorUtility.DisplayProgressBar("Defining Package Dependencies", $"Assigning dependencies for {installable.group.PackageName}", progress);
                    identity.Dependencies = new Manifest[installable.dependencies.Length];
                    for (int i = 0; i < installable.dependencies.Length; i++)
                    {
                        var installableDependency = installable.dependencies[i];

                        EditorUtility.DisplayProgressBar("Defining Package Dependencies",
                                                         $"Assigning {installableDependency.group.PackageName} to {identity.Name}",
                                                         progress += stepSize / installable.dependencies.Length);

                        var manifestFileName        = $"{installableDependency.group.PackageName}.asset";
                        var dependencyAssetTempPath = PathExtensions.Combine(installableDependency.group.PackageDirectory, manifestFileName);
                        var manifest = AssetDatabase.LoadAssetAtPath <Manifest>(dependencyAssetTempPath);

                        if (!manifest)
                        {
                            var packageManifests = AssetDatabase.FindAssets($"t:{nameof(Manifest)}", new string[] { "Assets", "Packages" }).Select(x => AssetDatabase.GUIDToAssetPath(x)).ToArray();
                            manifest = packageManifests.Where(x => x.Contains(manifestFileName)).Select(x => AssetDatabase.LoadAssetAtPath <Manifest>(x)).FirstOrDefault();
                        }

                        identity.Dependencies[i] = manifest;
                    }
                    EditorUtility.SetDirty(installableManifest);
                    EditorUtility.SetDirty(identity);
                }

                EditorUtility.DisplayProgressBar("Installing Package Files", $"{installSet.Length} packages", progress);
                foreach (var installable in installSet)
                {
                    string packageDirectory = installable.group.InstallDirectory;

                    EditorUtility.DisplayProgressBar("Installing Package Files", $"Downloading {installable.group.PackageName}", progress += stepSize / 2);

                    installable.group.Source.OnInstallPackageFiles(installable, packageDirectory);

                    foreach (var assemblyPath in Directory.GetFiles(packageDirectory, "*.dll", SearchOption.AllDirectories))
                    {
                        PackageHelper.WriteAssemblyMetaData(assemblyPath, $"{assemblyPath}.meta");
                    }
                }
            }
            finally
            {
                EditorUtility.ClearProgressBar();
                AssetDatabase.SaveAssets();

                EditorApplication.update += OneRefresh;

                RefreshWait = EditorApplication.timeSinceStartup;
                EditorApplication.UnlockReloadAssemblies();
            }
        }
Esempio n. 3
0
        private static void PackagesWatcher_Created(object sender, FileSystemEventArgs e)
        {
            string filePath = e.FullPath;

            EditorApplication.update += InstallPackage;

            void InstallPackage()
            {
                try
                {
                    EditorApplication.update -= InstallPackage;

                    AssetDatabase.StartAssetEditing();

                    string fileNameNoExt  = Path.GetFileNameWithoutExtension(filePath);
                    var    dependencyPath = Path.Combine(Packages, fileNameNoExt);
                    if (Directory.Exists(dependencyPath))
                    {
                        Directory.Delete(dependencyPath, true);
                    }
                    if (File.Exists($"{dependencyPath}.meta"))
                    {
                        File.Delete($"{dependencyPath}.meta");
                    }

                    Directory.CreateDirectory(dependencyPath);

                    using (var fileStream = File.OpenRead(filePath))
                        using (var archive = new ZipArchive(fileStream))
                            foreach (var entry in archive.Entries)
                            {
                                if (entry.FullName.ToLower().EndsWith("/") || entry.FullName.ToLower().EndsWith("\\"))
                                {
                                    continue;
                                }

                                var outputPath = Path.Combine(dependencyPath, entry.FullName);
                                var outputDir  = Path.GetDirectoryName(outputPath);
                                var fileName   = Path.GetFileName(outputPath);

                                if (!Directory.Exists(outputDir))
                                {
                                    Directory.CreateDirectory(outputDir);
                                }

                                entry.ExtractToFile(outputPath);
                                if (Path.GetExtension(fileName).Equals(".dll"))
                                {
                                    string assemblyPath = outputPath;
                                    PackageHelper.WriteAssemblyMetaData(assemblyPath, $"{assemblyPath}.meta");
                                }
                                if ("manifest.json".Equals(fileName.ToLower()))
                                {
                                    var stubManifest = CreateThunderstoreManifest.LoadStub(outputPath);
                                    var authorAlias  = fileNameNoExt.Substring(0, fileNameNoExt.IndexOf('-'));
                                    PackageHelper.GeneratePackageManifest(
                                        stubManifest.name.ToLower(), outputDir,
                                        stubManifest.name, authorAlias,
                                        stubManifest.version_number,
                                        stubManifest.description,
                                        stubManifest.website_url);
                                }
                            }
                    File.Delete(filePath);
                }
                finally
                {
                    AssetDatabase.StopAssetEditing();
                    AssetDatabase.Refresh();
                }
            }
        }