Ejemplo n.º 1
0
        private bool TryGetEnginePluginFromSolution(CppUE4SolutionDetector solutionDetector,
                                                    UnrealPluginInstallInfo installInfo)
        {
            var engineRootFolder = solutionDetector.UE4SourcesPath.Directory;

            return(TryGetEnginePluginFromEngineRoot(installInfo, engineRootFolder));
        }
Ejemplo n.º 2
0
        private static bool TryGetEnginePluginFromEngineRoot(UnrealPluginInstallInfo installInfo,
                                                             FileSystemPath engineRootFolder)
        {
            var upluginFilePath = engineRootFolder / ourPathToEnginePlugin;

            installInfo.EnginePlugin = GetPluginInfo(upluginFilePath);
            return(installInfo.EnginePlugin.IsPluginAvailable);
        }
Ejemplo n.º 3
0
 private void QueueAutoUpdate(UnrealPluginInstallInfo unrealPluginInstallInfo)
 {
     mySolution.Locks.ExecuteOrQueueReadLockEx(Lifetime,
                                               "UnrealPluginInstaller.InstallPluginIfRequired",
                                               () => HandleManualInstallPlugin(
                                                   new InstallPluginDescription(unrealPluginInstallInfo.Location, ForceInstall.No)
                                                   ));
 }
Ejemplo n.º 4
0
        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);
            });
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        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));
        }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
        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));
            });
        }
Ejemplo n.º 9
0
        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);
        }
Ejemplo n.º 10
0
        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));
        }
Ejemplo n.º 11
0
        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);
        }
Ejemplo n.º 12
0
        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);
        }
Ejemplo n.º 13
0
        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);
        }
Ejemplo n.º 14
0
        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);
        }
Ejemplo n.º 15
0
        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);
                }));
            });
        }
Ejemplo n.º 16
0
 public static void RefreshProjects(Lifetime parentLifetime, [NotNull] ISolution solution,
                                    [NotNull] UnrealPluginInstallInfo installInfo)
 {
     RefreshProjects(parentLifetime, solution, installInfo.ProjectPlugins.FirstOrDefault(null), installInfo.EngineRoot);
 }
Ejemplo n.º 17
0
        private UnrealPluginInstallInfo.InstallDescription GetProjectPluginForUproject(FileSystemPath uprojectLocation,
                                                                                       UnrealPluginInstallInfo installInfo)
        {
            var projectRoot     = uprojectLocation.Directory;
            var upluginLocation = projectRoot / ourPathToProjectPlugin;

            return(GetPluginInfo(upluginLocation, uprojectLocation));
        }