private bool TryGetEnginePluginFromSolution(CppUE4SolutionDetector solutionDetector, UnrealPluginInstallInfo installInfo) { var engineRootFolder = solutionDetector.UE4SourcesPath.Directory; return(TryGetEnginePluginFromEngineRoot(installInfo, engineRootFolder)); }
private static bool TryGetEnginePluginFromEngineRoot(UnrealPluginInstallInfo installInfo, FileSystemPath engineRootFolder) { var upluginFilePath = engineRootFolder / ourPathToEnginePlugin; installInfo.EnginePlugin = GetPluginInfo(upluginFilePath); return(installInfo.EnginePlugin.IsPluginAvailable); }
private void QueueAutoUpdate(UnrealPluginInstallInfo unrealPluginInstallInfo) { mySolution.Locks.ExecuteOrQueueReadLockEx(Lifetime, "UnrealPluginInstaller.InstallPluginIfRequired", () => HandleManualInstallPlugin( new InstallPluginDescription(unrealPluginInstallInfo.Location, ForceInstall.No) )); }
public UnrealPluginDetector(Lifetime lifetime, ILogger logger, UnrealHost unrealHost, CppUE4SolutionDetector solutionDetector, ISolution solution) { myLifetime = lifetime; InstallInfoProperty = new Property <UnrealPluginInstallInfo>(myLifetime, "UnrealPlugin.InstallInfoNotification", null, true); myLogger = logger; myUnrealHost = unrealHost; mySolution = solution; mySolutionDetector = solutionDetector; mySolutionDetector.IsUE4Solution_Observable.Change.Advise_When(myLifetime, newValue => newValue == TriBool.True, isUESolution => { myUnrealVersion = new Version(4, mySolutionDetector.UE4Version, mySolutionDetector.UE4PatchVersion); var installInfo = new UnrealPluginInstallInfo(); var foundEnginePlugin = TryGetEnginePluginFromSolution(mySolution, installInfo); var uprojectLocations = mySolution.GetAllProjects().SelectMany(project => project.GetAllProjectFiles(projectFile => { var location = projectFile.Location; if (location == null || !location.ExistsFile) { return(false); } return(location.ExtensionNoDot == UPROJECT_FILE_FORMAT && location.NameWithoutExtension == project.Name); })).Select(file => file.Location).ToSet(); if (!foundEnginePlugin) { // All projects in the solution are bound to the same engine // So take first project and use it to find Unreal Engine foundEnginePlugin = TryGetEnginePluginFromUproject(uprojectLocations.FirstNotNull(), installInfo); } if (!foundEnginePlugin) { // We didn't find Engine plugins, let's gather data about Project plugins foreach (var uprojectLocation in uprojectLocations) { var projectPlugin = GetProjectPluginForUproject(uprojectLocation, installInfo); installInfo.ProjectPlugins.Add(projectPlugin); } } InstallInfoProperty.SetValue(installInfo); }); }
private bool TryGetEnginePluginFromEngineRoot(UnrealPluginInstallInfo installInfo, FileSystemPath engineRootFolder) { var upluginFilePath = engineRootFolder / ourPathToEnginePlugin; installInfo.EnginePlugin = GetPluginInfo(upluginFilePath); if (installInfo.EnginePlugin.IsPluginAvailable) { myLogger.Info($"[UnrealLink]: found plugin {installInfo.EnginePlugin.UnrealPluginRootFolder}"); } return(installInfo.EnginePlugin.IsPluginAvailable); }
private static bool TryGetEnginePluginFromSolution(ISolution solution, UnrealPluginInstallInfo installInfo) { var engineProject = solution.GetProjectsByName("UE4").FirstNotNull(); if (engineProject?.ProjectFile == null) { return(false); } var engineProjectFile = engineProject.ProjectFile; var engineRootFolder = engineProjectFile.Location.Directory.Directory.Directory; return(TryGetEnginePluginFromEngineRoot(installInfo, engineRootFolder)); }
private void InstallPluginInGame(Lifetime lifetime, UnrealPluginInstallInfo unrealPluginInstallInfo, Property <double> progress) { myLogger.Verbose("[UnrealLink]: Installing plugin in Game"); var backupDir = VirtualFileSystemDefinition.CreateTemporaryDirectory(InteractionContext.SolutionContext, null, TMP_PREFIX); using var deleteTempFolders = new DeleteTempFolders(backupDir.Directory); var backupAllPlugins = BackupAllPlugins(unrealPluginInstallInfo); var success = true; var size = unrealPluginInstallInfo.ProjectPlugins.Count; var range = 1.0 / size; for (int i = 0; i < unrealPluginInstallInfo.ProjectPlugins.Count; i++) { progress.Value = range * i; var installDescription = unrealPluginInstallInfo.ProjectPlugins[i]; myLogger.Verbose($"[UnrealLink]: Installing plugin for {installDescription.ProjectName}"); try { if (InstallPlugin(lifetime, installDescription, unrealPluginInstallInfo.EngineRoot, progress, range)) { continue; } } catch (OperationCanceledException) { // Operation was cancelled, don't need to do anything, fallback to break case } success = false; break; } if (success) { unrealPluginInstallInfo.EnginePlugin.IsPluginAvailable = false; } else { foreach (var backupAllPlugin in backupAllPlugins) { backupAllPlugin.Restore(); } } myUnrealHost.myModel.InstallPluginFinished(success); }
private void HandleAutoUpdatePlugin(UnrealPluginInstallInfo unrealPluginInstallInfo) { var status = PluginInstallStatus.NoPlugin; var outOfSync = true; Version installedVersion = new Version(); if (unrealPluginInstallInfo.Location == PluginInstallLocation.Engine) { status = PluginInstallStatus.InEngine; outOfSync = unrealPluginInstallInfo.EnginePlugin.PluginVersion != myPathsProvider.CurrentPluginVersion; installedVersion = unrealPluginInstallInfo.EnginePlugin.PluginVersion; } if (unrealPluginInstallInfo.Location == PluginInstallLocation.Game) { status = PluginInstallStatus.InGame; outOfSync = unrealPluginInstallInfo.ProjectPlugins.Any(description => { var isNotSynced = description.PluginVersion != myPathsProvider.CurrentPluginVersion; if (isNotSynced) { installedVersion = description.PluginVersion; } return(isNotSynced); }); } if (!outOfSync) { return; } if (myBoundSettingsStore.GetValue((UnrealLinkSettings s) => s.InstallRiderLinkPlugin)) { QueueAutoUpdate(unrealPluginInstallInfo); return; } myLogger.Warn("[UnrealLink]: Plugin is out of sync"); myUnrealHost.PerformModelAction(model => { var isGameAvailable = !unrealPluginInstallInfo.ProjectPlugins.IsEmpty(); var isEngineAvailable = myPluginDetector.IsValidEngine(); model.OnEditorPluginOutOfSync(new EditorPluginOutOfSync( installedVersion.ToString(), myPathsProvider.CurrentPluginVersion.ToString(), status, isGameAvailable, isEngineAvailable)); }); }
private async Task InstallPluginInEngineIfRequired(Lifetime lifetime, UnrealPluginInstallInfo unrealPluginInstallInfo, IProperty <double> progress, ForceInstall forceInstall) { if (forceInstall == ForceInstall.No && unrealPluginInstallInfo.EnginePlugin.IsPluginAvailable && unrealPluginInstallInfo.EnginePlugin.PluginVersion == myPathsProvider.CurrentPluginVersion) { myLogger.Info("[UnrealLink] Plugin is up to date"); myLogger.Info( $"[UnrealLInk] Installed in Engine plugin version: {unrealPluginInstallInfo.EnginePlugin.PluginVersion}"); return; } await InstallPluginInEngine(lifetime, unrealPluginInstallInfo, progress); }
private bool TryGetEnginePluginFromUproject(FileSystemPath uprojectPath, UnrealPluginInstallInfo installInfo) { if (!uprojectPath.ExistsFile) { return(false); } var unrealEngineRoot = UnrealEngineFolderFinder.FindUnrealEngineRoot(uprojectPath); if (unrealEngineRoot.IsEmpty) { return(false); } return(TryGetEnginePluginFromEngineRoot(installInfo, unrealEngineRoot)); }
private async Task InstallPluginInGame(Lifetime lifetime, UnrealPluginInstallInfo unrealPluginInstallInfo, Property <double> progress) { var backupDir = FileSystemDefinition.CreateTemporaryDirectory(null, TMP_PREFIX); using var deleteTempFolders = new DeleteTempFolders(backupDir.Directory); var backupAllPlugins = BackupAllPlugins(unrealPluginInstallInfo); var success = true; var size = unrealPluginInstallInfo.ProjectPlugins.Count; var range = 1.0 / size; for (int i = 0; i < unrealPluginInstallInfo.ProjectPlugins.Count; i++) { progress.Value = range * i; var installDescription = unrealPluginInstallInfo.ProjectPlugins[i]; try { if (await InstallPlugin(lifetime, installDescription, installDescription.UprojectFilePath, progress, range)) { continue; } } catch (OperationCanceledException) { // Operation was cancelled, don't need to do anything, fallback to break case } success = false; break; } if (success) { unrealPluginInstallInfo.EnginePlugin.IsPluginAvailable = false; } else { foreach (var backupAllPlugin in backupAllPlugins) { backupAllPlugin.Restore(); } } myUnrealHost.myModel.InstallPluginFinished(success); }
private List <BackupDir> BackupAllPlugins(UnrealPluginInstallInfo unrealPluginInstallInfo) { var result = new List <BackupDir>(); if (unrealPluginInstallInfo.EnginePlugin.IsPluginAvailable) { try { result.Add(new BackupDir(unrealPluginInstallInfo.EnginePlugin.UnrealPluginRootFolder, TMP_PREFIX)); } catch { var text = "Close all running instances of Unreal Editor and try again\n" + $"Path to old plugin: {unrealPluginInstallInfo.EnginePlugin.UnrealPluginRootFolder}"; myUnrealHost.myModel.RiderLinkInstallMessage( new InstallMessage("Failed to backup old RiderLink plugin", ContentType.Error)); myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(text, ContentType.Error)); throw; } } foreach (var installDescription in unrealPluginInstallInfo.ProjectPlugins) { try { if (installDescription.IsPluginAvailable) { result.Add(new BackupDir(installDescription.UnrealPluginRootFolder, TMP_PREFIX)); } } catch { var text = "Close all running instances of Unreal Editor and try again\n" + $"Path to old plugin: {installDescription.UnrealPluginRootFolder}"; myUnrealHost.myModel.RiderLinkInstallMessage( new InstallMessage("Failed to backup old RiderLink plugin", ContentType.Error)); myUnrealHost.myModel.RiderLinkInstallMessage(new InstallMessage(text, ContentType.Error)); throw; } } return(result); }
private async Task InstallPluginInGameIfRequired(Lifetime lifetime, UnrealPluginInstallInfo unrealPluginInstallInfo, Property <double> progress, ForceInstall forceInstall) { if (forceInstall == ForceInstall.No && unrealPluginInstallInfo.ProjectPlugins.All(description => description.IsPluginAvailable && description.PluginVersion == myPathsProvider.CurrentPluginVersion)) { myLogger.Info("[UnrealLink] Plugin is up to date"); foreach (var installDescription in unrealPluginInstallInfo.ProjectPlugins) { myLogger.Info( $"[UnrealLInk] Installed in {installDescription.UprojectFilePath.NameWithoutExtension} plugin version: {unrealPluginInstallInfo.EnginePlugin.PluginVersion}"); } return; } await InstallPluginInGame(lifetime, unrealPluginInstallInfo, progress); }
private async Task InstallPluginInEngine(Lifetime lifetime, UnrealPluginInstallInfo unrealPluginInstallInfo, IProperty <double> progress) { var backupDir = FileSystemDefinition.CreateTemporaryDirectory(null, TMP_PREFIX); using var deleteTempFolders = new DeleteTempFolders(backupDir.Directory); var backupAllPlugins = BackupAllPlugins(unrealPluginInstallInfo); progress.Value = 0.0; bool success; try { success = await InstallPlugin(lifetime, unrealPluginInstallInfo.EnginePlugin, unrealPluginInstallInfo.ProjectPlugins.First().UprojectFilePath, progress, 1.0); } catch (OperationCanceledException) { success = false; } if (!success) { foreach (var backupAllPlugin in backupAllPlugins) { backupAllPlugin.Restore(); } } else { foreach (var installDescription in unrealPluginInstallInfo.ProjectPlugins) { installDescription.IsPluginAvailable = false; } } myUnrealHost.myModel.InstallPluginFinished(success); }
public UnrealPluginDetector(Lifetime lifetime, ILogger logger, CppUE4SolutionDetector solutionDetector, ISolution solution, IShellLocks locks, ISolutionLoadTasksScheduler scheduler) { myLifetime = lifetime; InstallInfoProperty = new Property <UnrealPluginInstallInfo>(myLifetime, "UnrealPlugin.InstallInfoNotification", null, true); myLogger = logger; mySolution = solution; mySolutionDetector = solutionDetector; mySolutionDetector.IsUE4Solution_Observable.Change.Advise_When(myLifetime, newValue => newValue == TriBool.True, _ => { scheduler.EnqueueTask(new SolutionLoadTask("Find installed RiderLink plugins", SolutionLoadTaskKinds.Done, () => { myLogger.Info("[UnrealLink]: Looking for RiderLink plugins"); myUnrealVersion = mySolutionDetector.Version; if (myUnrealVersion < myMinimalSupportedVersion) { locks.ExecuteOrQueue(myLifetime, "UnrealLink.CheckSupportedVersion", () => { var notification = new NotificationModel( $"Unreal Engine {myMinimalSupportedVersion}+ is required", $"<html>UnrealLink supports Unreal Engine versions starting with {myMinimalSupportedVersion}<br>" + "<b>WARNING: Advanced users only</b><br>" + "You can manually download the latest version of plugin and build It for your version of Unreal Editor<br>" + RiderContextNotificationHelper.MakeLink( "https://github.com/JetBrains/UnrealLink/releases/latest", "Download latest Unreal Editor plugin") + "</html>", true, RdNotificationEntryType.WARN, new List <NotificationHyperlink>()); var notificationsModel = Shell.Instance.GetComponent <NotificationsModel>(); notificationsModel.Notification(notification); }); return; } var installInfo = new UnrealPluginInstallInfo(); var foundEnginePlugin = TryGetEnginePluginFromSolution(solutionDetector, installInfo); ISet <FileSystemPath> uprojectLocations; using (solution.Locks.UsingReadLock()) { var allProjects = mySolution.GetAllProjects(); if (solutionDetector.SupportRiderProjectModel == CppUE4ProjectModelSupportMode.UprojectOpened) { uprojectLocations = allProjects.Where(project => { if (project.IsMiscProjectItem() || project.IsMiscFilesProject()) { return(false); } var location = project.Location; if (location == null) { return(false); } if (EXCLUDED_PROJECTS.Contains(location.NameWithoutExtension)) { return(false); } // TODO: drop this ugly check after updating to net211 where Location == "path/to/game.uproject" var isUproject = location.ExistsFile && location.ExtensionNoDot == UPROJECT_FILE_FORMAT && location.NameWithoutExtension == project.Name; return(isUproject || (location / $"{location.Name}.uproject").ExistsFile); }).Select(project => { var location = project.Location; if (location.ExistsFile) { return(location); } return(location / $"{location.Name}.uproject"); }).ToSet(); } else { uprojectLocations = allProjects.SelectMany(project => project.GetAllProjectFiles(projectFile => { var location = projectFile.Location; if (location == null || !location.ExistsFile) { return(false); } return(location.ExtensionNoDot == UPROJECT_FILE_FORMAT && location.NameWithoutExtension == project.Name); })).Select(file => file.Location).ToSet(); } } myLogger.Info($"[UnrealLink]: Found {uprojectLocations.Count} uprojects"); if (!foundEnginePlugin && !uprojectLocations.IsEmpty()) { // All projects in the solution are bound to the same engine // So take first project and use it to find Unreal Engine TryGetEnginePluginFromUproject(uprojectLocations.FirstNotNull(), installInfo); foundEnginePlugin = installInfo.EnginePlugin.IsPluginAvailable; } // Gather data about Project plugins foreach (var uprojectLocation in uprojectLocations) { myLogger.Info($"[UnrealLink]: Looking for plugin in {uprojectLocation}"); var projectPlugin = GetProjectPluginForUproject(uprojectLocation); if (projectPlugin.IsPluginAvailable) { myLogger.Info( $"[UnrealLink]: found plugin {projectPlugin.UnrealPluginRootFolder}"); } installInfo.ProjectPlugins.Add(projectPlugin); } if (foundEnginePlugin) { installInfo.Location = PluginInstallLocation.Engine; } else if (installInfo.ProjectPlugins.Any(description => description.IsPluginAvailable)) { installInfo.Location = PluginInstallLocation.Game; } else { installInfo.Location = PluginInstallLocation.NotInstalled; } InstallInfoProperty.SetValue(installInfo); })); }); }
public static void RefreshProjects(Lifetime parentLifetime, [NotNull] ISolution solution, [NotNull] UnrealPluginInstallInfo installInfo) { RefreshProjects(parentLifetime, solution, installInfo.ProjectPlugins.FirstOrDefault(null), installInfo.EngineRoot); }
private UnrealPluginInstallInfo.InstallDescription GetProjectPluginForUproject(FileSystemPath uprojectLocation, UnrealPluginInstallInfo installInfo) { var projectRoot = uprojectLocation.Directory; var upluginLocation = projectRoot / ourPathToProjectPlugin; return(GetPluginInfo(upluginLocation, uprojectLocation)); }