/// <summary> /// Called when Package Manager has completed a remove request. /// </summary> static void CompleteUninstallEvent() { var targetPack = s_CurrentEvent.targetPack; var removeRequest = s_CurrentEvent.request as RemoveRequest; if (removeRequest == null) { return; } if (removeRequest.Status == StatusCode.Failure) { targetPack.InstallStatus &= ~(InstallationStatus.UninstallRequested | InstallationStatus.Locked); OnUninstallContent?.Invoke(false, removeRequest.Error.message); OnContentChanged?.Invoke(); return; } targetPack.InstallStatus = InstallationStatus.Unknown; OnUninstallContent?.Invoke(true, $"Successfully uninstalled {s_CurrentEvent.targetPack.PackageName}"); OnContentChanged?.Invoke(); // We do an update here to ensure icon state is maintained - enough can change between dependencies and cross-references that just changing the target pack can be misleading if (QueuedEvents.Count == 0) { UpdateContentStatus(); } }
/// <summary> /// Attempts to install the sample associated with the currently active Content Pack. /// </summary> static void ProcessSampleEvent() { var targetPack = s_CurrentEvent.targetPack; var samples = Sample.FindByPackage(targetPack.PackageName, targetPack.Version); // We manually set the event null this time because we have no asynchronous request to process s_CurrentEvent = null; if (!samples.Any()) { targetPack.InstallStatus &= ~InstallationStatus.Installing; OnInstallContent?.Invoke(false, $"Can't install content - no sample available."); OnContentChanged?.Invoke(); return; } var targetSample = samples.First(); if (!targetSample.Import()) { targetPack.InstallStatus &= ~InstallationStatus.Installing; OnInstallContent?.Invoke(false, $"Failed to import associated content sample."); OnContentChanged?.Invoke(); return; } FinishInstallation(targetPack); }
/// <summary> /// Attempts to embed a package specified within the currently active Content Pack. /// </summary> static void StartEmbedEvent() { var targetPack = s_CurrentEvent.targetPack; ConditionalLog($"Start Embed Event {targetPack.DisplayName}"); targetPack.InstallStatus |= InstallationStatus.Locked; s_CurrentEvent.request = Client.Embed(targetPack.PackageName); OnContentChanged?.Invoke(); }
static void FinishInstallation(ContentPack targetPack) { targetPack.InstallStatus = InstallationStatus.Installed; OnInstallContent?.Invoke(true, $"Successfully installed {targetPack.PackageName}"); OnContentChanged?.Invoke(); // We do an update here to ensure icon state is maintained - enough can change between dependencies and cross-references that just changing the target pack can be misleading if (QueuedEvents.Count == 0) { UpdateContentStatus(); } }
/// <summary> /// Attempts to remove the package that the currently active event contains. /// </summary> static void StartUninstallEvent() { // If the package is not installed, do nothing. if (!s_CurrentEvent.targetPack.InstallStatus.HasFlag(InstallationStatus.Installed)) { OnUninstallContent?.Invoke(true, $"{s_CurrentEvent.targetPack.PackageName} not installed"); s_CurrentEvent = null; return; } s_CurrentEvent.targetPack.InstallStatus |= InstallationStatus.Locked; s_CurrentEvent.request = Client.Remove(s_CurrentEvent.targetPack.PackageName); OnContentChanged?.Invoke(); }
/// <summary> /// Queues up an uninstallation of a Content Pack. /// </summary> /// <param name="contentToUninstall">The Content Pack to uninstall</param> internal static void UninstallContent(ContentPack contentToUninstall) { ConditionalLog($"UninstallContent {contentToUninstall.DisplayName}"); // Check if this content is already queued up for uninstall if (contentToUninstall.InstallStatus.HasFlag(InstallationStatus.UninstallQueued)) { return; } StartEditorUpdates(); contentToUninstall.InstallStatus |= InstallationStatus.UninstallQueued; QueuedEvents.Add(new ContentEvent { action = PackageAction.Remove, targetPack = contentToUninstall }); OnContentChanged?.Invoke(); }
/// <summary> /// Called internally to go from installing a package to installing a sample. /// </summary> /// <param name="contentToInstall">The Content Pack that contains a sample to install</param> static void InstallContentSample(ContentPack contentToInstall) { ConditionalLog($"InstallContentSample {contentToInstall.DisplayName}"); // Content must be installed or installing to add a sample if (!(contentToInstall.InstallStatus.HasFlag(InstallationStatus.Installed) || contentToInstall.InstallStatus.HasFlag(InstallationStatus.Installing))) { return; } StartEditorUpdates(); contentToInstall.InstallStatus |= InstallationStatus.InstallQueued; // We stick the sample event at the beginning of the list because it happens automatically after an install QueuedEvents.Insert(0, new ContentEvent { action = PackageAction.SampleInstall, targetPack = contentToInstall }); OnContentChanged?.Invoke(); }
/// <summary> /// Called internally to go from installing a package to making it writeable. /// </summary> /// <param name="contentToEmbed">The Content Pack to make a writeable package</param> static void EmbedContent(ContentPack contentToEmbed) { ConditionalLog($"EmbedContent {contentToEmbed.DisplayName}"); // Content must be installed or installing to embed if (!(contentToEmbed.InstallStatus.HasFlag(InstallationStatus.Installed) || contentToEmbed.InstallStatus.HasFlag(InstallationStatus.Installing))) { return; } StartEditorUpdates(); contentToEmbed.InstallStatus |= InstallationStatus.InstallQueued; // We stick the embed event at the beginning of the list because it happens automatically after an install QueuedEvents.Insert(0, new ContentEvent { action = PackageAction.Embed, targetPack = contentToEmbed }); OnContentChanged?.Invoke(); }
/// <summary> /// Stops any pending Content Manager actions relating to a particular Content Pack. /// </summary> /// <param name="contentToCancel">The Content Pack to stop all actions for</param> internal static void CancelContentAction(ContentPack contentToCancel) { var eventQueue = QueuedEvents; ConditionalLog($"CancelContentAction {contentToCancel.DisplayName}"); // Search through the queued content list for events concerning this content pack var cancelableEvents = eventQueue.Where(entry => entry.targetPack == contentToCancel).ToList(); // Remove them foreach (var targetEvent in cancelableEvents) { eventQueue.Remove(targetEvent); } // Undo any queued flags contentToCancel.InstallStatus &= ~(InstallationStatus.InstallQueued | InstallationStatus.UninstallRequested); OnContentChanged?.Invoke(); }
/// <summary> /// Called when Package Manager has completed the embed request. /// </summary> static void CompleteEmbedEvent() { var targetPack = s_CurrentEvent.targetPack; var embedRequest = s_CurrentEvent.request as EmbedRequest; ConditionalLog($"Complete Embed Event {targetPack.DisplayName}"); if (embedRequest == null) { return; } if (embedRequest.Status == StatusCode.Failure) { targetPack.InstallStatus &= ~InstallationStatus.Installing; OnInstallContent?.Invoke(false, $"Embed: {embedRequest.Error.message}"); OnContentChanged?.Invoke(); return; } FinishInstallation(targetPack); }
/// <summary> /// Called when the Package Manager has completed the add request. /// Queues up additional actions if the content is set to be installed to the project folder. /// </summary> static void CompleteAddEvent() { var targetPack = s_CurrentEvent.targetPack; var addRequest = s_CurrentEvent.request as AddRequest; if (addRequest == null) { return; } if (addRequest.Status == StatusCode.Failure) { targetPack.InstallStatus &= ~InstallationStatus.Installing; OnInstallContent?.Invoke(false, addRequest.Error.message); OnContentChanged?.Invoke(); return; } switch (targetPack.InstallType) { case InstallationType.Package: FinishInstallation(targetPack); break; case InstallationType.WriteablePackage: EmbedContent(targetPack); break; case InstallationType.UnityPackage: InstallContentSample(targetPack); // Update the status so the sample can be found UpdateContentStatus(); break; } }
/// <summary> /// Attempts to install a package specified within the currently active Content Pack. /// </summary> static void StartAddEvent() { // Is the package already installed? Do nothing // Otherwise, start an add action if (s_CurrentEvent.targetPack.InstallStatus.HasFlag(InstallationStatus.Installed) && !s_CurrentEvent.targetPack.InstallStatus.HasFlag(InstallationStatus.DifferentVersion)) { OnInstallContent?.Invoke(true, $"{s_CurrentEvent.targetPack.PackageName} already installed"); s_CurrentEvent = null; return; } s_CurrentEvent.targetPack.InstallStatus |= InstallationStatus.Locked; var currentUrl = s_CurrentEvent.targetPack.Url.ToLower(); if (currentUrl.StartsWith(k_PackageReferenceKey)) { // Local content packs can be in embedded packages, which is fine // Or they can be in the library folder, in which case we need to copy them to a temporary folder for installation currentUrl = Path.GetFullPath(currentUrl).ToLower(); if (currentUrl.StartsWith(s_CachedPackagePath)) { try { // The content pack is located within the library folder - we must copy it to a temporary folder var localPackageInfo = new DirectoryInfo(currentUrl); if (localPackageInfo.Exists) { var localFolder = localPackageInfo.Name; var targetPath = $"{Path.GetDirectoryName(Application.dataPath)}{Path.DirectorySeparatorChar}{k_LocalPackagePath}{Path.DirectorySeparatorChar}{localFolder}"; Directory.CreateDirectory(targetPath); FileUtil.ReplaceDirectory(currentUrl.Replace(Path.DirectorySeparatorChar, '/'), targetPath.Replace(Path.DirectorySeparatorChar, '/')); currentUrl = $"file:{ToRelativeUnityPath(targetPath)}"; } else { OnInstallContent?.Invoke(false, $"{s_CurrentEvent.targetPack.PackageName} cannot be found"); s_CurrentEvent = null; return; } } catch (Exception ex) { OnInstallContent?.Invoke(false, $"Exception installing {s_CurrentEvent?.targetPack.PackageName}:{ex.Message}"); s_CurrentEvent = null; return; } } else { // Convert the packages path to a relative path for version control niceness currentUrl = $"file:{ToRelativeUnityPath(Path.GetFullPath(currentUrl))}"; } } if (!string.IsNullOrEmpty(s_CurrentEvent.targetPack.AutoVersion)) { currentUrl += $"@{s_CurrentEvent.targetPack.AutoVersion}"; } s_CurrentEvent.request = Client.Add(currentUrl); OnContentChanged?.Invoke(); }