private void SetValues() { IsUnityProjectFolder.SetValue(HasUnityFileStructure(mySolution.SolutionDirectory)); IsUnityProject.SetValue(IsUnityProjectFolder.Value && mySolution.IsValid() && mySolution.SolutionFilePath.ExtensionNoDot.ToLower() == "sln"); IsUnityGeneratedProject.SetValue(IsUnityProject.Value && SolutionNameMatchesUnityProjectName()); }
private void NotifyHasUnityReference() { if (!HasUnityReference.Value) { HasUnityReference.SetValue(true); foreach (var handler in myHandlers) { handler.OnHasUnityReference(); } } }
public UnityVersion(UnityProjectFileCacheProvider unityProjectFileCache, ISolution solution, IFileSystemTracker fileSystemTracker, Lifetime lifetime, UnitySolutionTracker unitySolutionTracker) { myUnityProjectFileCache = unityProjectFileCache; mySolution = solution; unitySolutionTracker.IsUnityProjectFolder.AdviseOnce(lifetime, args => { if (!args) { return; } var projectVersionTxtPath = mySolution.SolutionDirectory.Combine("ProjectSettings/ProjectVersion.txt"); fileSystemTracker.AdviseFileChanges(lifetime, projectVersionTxtPath, _ => { myVersionFromProjectVersionTxt = TryGetVersionFromProjectVersion(projectVersionTxtPath); ActualVersionForSolution.SetValue(myVersionFromProjectVersionTxt ?? GetActualVersionForSolution()); }); myVersionFromProjectVersionTxt = TryGetVersionFromProjectVersion(projectVersionTxtPath); var editorInstanceJsonPath = mySolution.SolutionDirectory.Combine("Library/EditorInstance.json"); fileSystemTracker.AdviseFileChanges(lifetime, editorInstanceJsonPath, _ => { myVersionFromEditorInstanceJson = TryGetApplicationPathFromEditorInstanceJson(editorInstanceJsonPath); }); myVersionFromEditorInstanceJson = TryGetApplicationPathFromEditorInstanceJson(editorInstanceJsonPath); ActualVersionForSolution.SetValue(GetActualVersionForSolution()); }); }
private void OnSolutionPreparePsiModules() { myChangeManager.RegisterChangeProvider(myLifetime, this); myChangeManager.AddDependency(myLifetime, this, myModuleReferenceResolveSync); // Track the lifetime of all projects, so we can pass it to the handler later myProjects.Projects.View(myLifetime, (projectLifetime, project) => myProjectLifetimes.Add(project, projectLifetime)); var unityProjectLifetimes = myProjectLifetimes.Where(pl => pl.Key.IsUnityProject()).ToList(); if (unityProjectLifetimes.Any()) { HasUnityReference.SetValue(true); } foreach (var handler in myHandlers) { foreach (var(project, lifetime) in unityProjectLifetimes) { handler.OnUnityProjectAdded(lifetime, project); } } }
private void CreateProtocols(FileSystemPath protocolInstancePath) { if (!protocolInstancePath.ExistsFile) { return; } List <ProtocolInstance> protocolInstanceList; try { protocolInstanceList = ProtocolInstance.FromJson(protocolInstancePath.ReadAllText2().Text); } catch (Exception e) { myLogger.Warn($"Unable to parse {protocolInstancePath}" + Environment.NewLine + e); return; } var protocolInstance = protocolInstanceList?.SingleOrDefault(a => a.SolutionName == mySolution.SolutionFilePath.NameWithoutExtension); if (protocolInstance == null) { return; } myLogger.Info($"EditorPlugin protocol port {protocolInstance.Port} for Solution: {protocolInstance.SolutionName}."); try { var lifetime = mySessionLifetimes.Next(); myLogger.Info("Create protocol..."); myLogger.Info("Creating SocketWire with port = {0}", protocolInstance.Port); var wire = new SocketWire.Client(lifetime, myDispatcher, protocolInstance.Port, "UnityClient"); var protocol = new Protocol("UnityEditorPlugin", new Serializers(), new Identities(IdKind.Client), myDispatcher, wire, lifetime); protocol.ThrowErrorOnOutOfSyncModels = false; protocol.OutOfSyncModels.AdviseOnce(lifetime, e => { if (myPluginInstallations.Contains(mySolution.SolutionFilePath)) { return; } myPluginInstallations.Add(mySolution.SolutionFilePath); // avoid displaying Notification multiple times on each AppDomain.Reload in Unity var appVersion = myUnityVersion.GetActualVersionForSolution(); if (appVersion < new Version(2019, 2)) { var entry = myBoundSettingsStore.Schema.GetScalarEntry((UnitySettings s) => s.InstallUnity3DRiderPlugin); var isEnabled = myBoundSettingsStore.GetValueProperty <bool>(lifetime, entry, null).Value; if (!isEnabled) { myHost.PerformModelAction(model => model.OnEditorModelOutOfSync()); } } else { var notification = new NotificationModel("Advanced Unity integration is unavailable", $"Please update External Editor to {myHostProductInfo.VersionMarketingString} in Unity Preferences.", true, RdNotificationEntryType.WARN); mySolution.Locks.ExecuteOrQueue(lifetime, "OutOfSyncModels.Notify", () => myNotificationsModel.Notification(notification)); } }); wire.Connected.WhenTrue(lifetime, lf => { myLogger.Info("WireConnected."); var editor = new EditorPluginModel(lf, protocol); editor.IsBackendConnected.Set(rdVoid => true); if (PlatformUtil.RuntimePlatform == PlatformUtil.Platform.Windows) { var frontendProcess = Process.GetCurrentProcess().GetParent(); // RiderProcessId is not used on non-Windows, but this line gives bad warning in the log if (frontendProcess != null) { editor.RiderProcessId.SetValue(frontendProcess.Id); } } myHost.PerformModelAction(m => m.SessionInitialized.Value = true); SubscribeToLogs(lf, editor); SubscribeToOpenFile(editor); editor.Play.Advise(lf, b => myHost.PerformModelAction(rd => rd.Play.SetValue(b))); editor.Pause.Advise(lf, b => myHost.PerformModelAction(rd => rd.Pause.SetValue(b))); editor.ClearOnPlay.Advise(lf, time => myHost.PerformModelAction(rd => rd.ClearOnPlay(time))); editor.UnityProcessId.View(lf, (_, pid) => myHost.PerformModelAction(t => t.UnityProcessId.Set(pid))); // I have split this into groups, because want to use async api for finding reference and pass them via groups to Unity myHost.PerformModelAction(t => t.ShowFileInUnity.Advise(lf, v => editor.ShowFileInUnity.Fire(v))); myHost.PerformModelAction(t => t.ShowPreferences.Advise(lf, v => { editor.ShowPreferences.Fire(); })); editor.EditorLogPath.Advise(lifetime, s => myHost.PerformModelAction(a => a.EditorLogPath.SetValue(s))); editor.PlayerLogPath.Advise(lifetime, s => myHost.PerformModelAction(a => a.PlayerLogPath.SetValue(s))); // Note that these are late-init properties. Once set, they are always set and do not allow nulls. // This means that if/when the Unity <-> Backend protocol closes, they still retain the last value // they had - so the front end will retain the log and application paths of the just-closed editor. // Opening a new editor instance will reconnect and push a new value through to the front end editor.UnityApplicationData.Advise(lifetime, s => myHost.PerformModelAction(a => { var version = UnityVersion.Parse(s.ApplicationVersion); a.UnityApplicationData.SetValue(new UnityApplicationData(s.ApplicationPath, s.ApplicationContentsPath, s.ApplicationVersion, UnityVersion.RequiresRiderPackage(version))); })); editor.ScriptCompilationDuringPlay.Advise(lifetime, s => myHost.PerformModelAction(a => a.ScriptCompilationDuringPlay.Set(ConvertToScriptCompilationEnum(s)))); myHost.PerformModelAction(rd => { rd.GenerateUIElementsSchema.Set((l, u) => editor.GenerateUIElementsSchema.Start(l, u).ToRdTask(l)); }); TrackActivity(editor, lf); if (!myComponentLifetime.IsTerminated) { myLocks.ExecuteOrQueueEx(myComponentLifetime, "setModel", () => { UnityModel.SetValue(editor); }); } lf.AddAction(() => { if (!myComponentLifetime.IsTerminated) { myLocks.ExecuteOrQueueEx(myComponentLifetime, "clearModel", () => { myLogger.Info("Wire disconnected."); myHost.PerformModelAction(m => m.SessionInitialized.Value = false); UnityModel.SetValue(null); }); } }); }); } catch (Exception ex) { myLogger.Error(ex); } }
private void ResetModel(Lifetime lf, IProtocol protocol) { myUnrealHost.PerformModelAction(riderModel => { UE4Library.RegisterDeclaredTypesSerializers(riderModel.SerializationContext.Serializers); riderModel.EditorId.SetValue(riderModel.EditorId.Value + 1); }); var unrealModel = new RdEditorModel(lf, protocol); UE4Library.RegisterDeclaredTypesSerializers(unrealModel.SerializationContext.Serializers); unrealModel.AllowSetForegroundWindow.Set((lt, pid) => { return(myUnrealHost.PerformModelAction(riderModel => riderModel.AllowSetForegroundWindow.Start(lt, pid)) as RdTask <bool>); }); unrealModel.UnrealLog.Advise(lf, logEvent => { myUnrealHost.PerformModelAction(riderModel => { OnMessageReceived(riderModel, logEvent); }); }); unrealModel.OnBlueprintAdded.Advise(lf, blueprintClass => { //todo }); unrealModel.Play.Advise(lf, val => { myUnrealHost.PerformModelAction(riderModel => { if (PlayedFromRider) { return; } try { PlayedFromUnreal = true; riderModel.Play.Set(val); } finally { PlayedFromUnreal = false; } }); }); unrealModel.PlayMode.Advise(lf, val => { myUnrealHost.PerformModelAction(riderModel => { if (PlayModeFromRider) { return; } try { PlayModeFromUnreal = true; riderModel.PlayMode.Set(val); } finally { PlayModeFromUnreal = false; } }); }); myUnrealHost.PerformModelAction(riderModel => { riderModel.FilterLinkCandidates.Set((lifetime, candidates) => RdTask <ILinkResponse[]> .Successful(candidates .Select(request => myLinkResolver.ResolveLink(request, unrealModel.IsBlueprintPathName)) .AsArray())); riderModel.IsMethodReference.Set((lifetime, methodReference) => { var b = myEditorNavigator.IsMethodReference(methodReference); return(RdTask <bool> .Successful(b)); }); riderModel.OpenBlueprint.Advise(lf, blueprintReference => OnOpenedBlueprint(unrealModel, blueprintReference)); riderModel.NavigateToClass.Advise(lf, uClass => myEditorNavigator.NavigateToClass(uClass)); riderModel.NavigateToMethod.Advise(lf, methodReference => myEditorNavigator.NavigateToMethod(methodReference)); riderModel.Play.Advise(lf, val => { if (PlayedFromUnreal) { return; } try { PlayedFromRider = true; unrealModel.Play.Set(val); } finally { PlayedFromRider = false; } }); riderModel.PlayMode.Advise(lf, val => { if (PlayModeFromUnreal) { return; } try { PlayModeFromRider = true; unrealModel.PlayMode.Set(val); } finally { PlayModeFromRider = false; } }); riderModel.FrameSkip.Advise(lf, skip => unrealModel.FrameSkip.Fire(skip)); }); if (myComponentLifetime.IsAlive) { myLocks.ExecuteOrQueueEx(myComponentLifetime, "setModel", () => { myEditorModel.SetValue(unrealModel); }); } }
private void CreateProtocols(FileSystemPath protocolInstancePath) { if (!protocolInstancePath.ExistsFile) { return; } List <ProtocolInstance> protocolInstanceList; try { protocolInstanceList = ProtocolInstance.FromJson(protocolInstancePath.ReadAllText2().Text); } catch (Exception e) { myLogger.Warn($"Unable to parse {protocolInstancePath}" + Environment.NewLine + e); return; } var protocolInstance = protocolInstanceList?.SingleOrDefault(a => a.SolutionName == mySolution.SolutionFilePath.NameWithoutExtension); if (protocolInstance == null) { return; } myLogger.Info($"EditorPlugin protocol port {protocolInstance.Port} for Solution: {protocolInstance.SolutionName}."); try { var lifetime = mySessionLifetimes.Next(); myLogger.Info("Create protocol..."); myLogger.Info("Creating SocketWire with port = {0}", protocolInstance.Port); var wire = new SocketWire.Client(lifetime, myDispatcher, protocolInstance.Port, "UnityClient"); wire.Connected.WhenTrue(lifetime, lf => { myLogger.Info("WireConnected."); var protocol = new Protocol("UnityEditorPlugin", new Serializers(), new Identities(IdKind.Client), myDispatcher, wire, lf); protocol.ThrowErrorOnOutOfSyncModels = false; protocol.OutOfSyncModels.Advise(lf, e => { var entry = myBoundSettingsStore.Schema.GetScalarEntry((UnitySettings s) => s.InstallUnity3DRiderPlugin); var isEnabled = myBoundSettingsStore.GetValueProperty <bool>(lf, entry, null).Value; if (!isEnabled) { myHost.PerformModelAction(model => model.OnEditorModelOutOfSync()); } }); var editor = new EditorPluginModel(lf, protocol); editor.IsBackendConnected.Set(rdVoid => true); if (PlatformUtil.RuntimePlatform == PlatformUtil.Platform.Windows) { var frontendProcess = Process.GetCurrentProcess().GetParent(); // RiderProcessId is not used on non-Windows, but this line gives bad warning in the log if (frontendProcess != null) { editor.RiderProcessId.SetValue(frontendProcess.Id); } } myHost.PerformModelAction(m => m.SessionInitialized.Value = true); SubscribeToLogs(lf, editor); SubscribeToOpenFile(editor); editor.Play.Advise(lf, b => myHost.PerformModelAction(rd => rd.Play.SetValue(b))); editor.Pause.Advise(lf, b => myHost.PerformModelAction(rd => rd.Pause.SetValue(b))); editor.ClearOnPlay.Advise(lf, time => myHost.PerformModelAction(rd => rd.ClearOnPlay(time))); editor.UnityProcessId.View(lf, (_, pid) => myHost.PerformModelAction(t => t.UnityProcessId.Set(pid))); // I have split this into groups, because want to use async api for finding reference and pass them via groups to Unity myHost.PerformModelAction(t => t.ShowGameObjectOnScene.Advise(lf, v => editor.ShowGameObjectOnScene.Fire(v.ConvertToUnityModel()))); myHost.PerformModelAction(t => t.ShowFileInUnity.Advise(lf, v => editor.ShowFileInUnity.Fire(v))); myHost.PerformModelAction(t => t.ShowPreferences.Advise(lf, v => { if (t.UnityProcessId.HasValue()) { UnityFocusUtil.FocusUnity(t.UnityProcessId.Value); } editor.ShowPreferences.Fire(); })); // pass all references to Unity TODO temp workaround, replace with async api myHost.PerformModelAction(t => t.FindUsageResults.Advise(lf, v => editor.FindUsageResults.Fire(v.ConvertToUnityModel()))); editor.EditorLogPath.Advise(lifetime, s => myHost.PerformModelAction(a => a.EditorLogPath.SetValue(s))); editor.PlayerLogPath.Advise(lifetime, s => myHost.PerformModelAction(a => a.PlayerLogPath.SetValue(s))); // Note that these are late-init properties. Once set, they are always set and do not allow nulls. // This means that if/when the Unity <-> Backend protocol closes, they still retain the last value // they had - so the front end will retain the log and application paths of the just-closed editor. // Opening a new editor instance will reconnect and push a new value through to the front end editor.ApplicationPath.Advise(lifetime, s => myHost.PerformModelAction(a => a.ApplicationPath.SetValue(s))); editor.ApplicationContentsPath.Advise(lifetime, s => myHost.PerformModelAction(a => a.ApplicationContentsPath.SetValue(s))); editor.ScriptCompilationDuringPlay.Advise(lifetime, s => myHost.PerformModelAction(a => a.ScriptCompilationDuringPlay.Set(ConvertToScriptCompilationEnum(s)))); BindPluginPathToSettings(lf, editor); TrackActivity(editor, lf); if (!myComponentLifetime.IsTerminated) { myLocks.ExecuteOrQueueEx(myComponentLifetime, "setModel", () => { UnityModel.SetValue(editor); }); } lf.AddAction(() => { if (!myComponentLifetime.IsTerminated) { myLocks.ExecuteOrQueueEx(myComponentLifetime, "clearModel", () => { myLogger.Info("Wire disconnected."); myHost.PerformModelAction(m => m.SessionInitialized.Value = false); UnityModel.SetValue(null); }); } }); }); } catch (Exception ex) { myLogger.Error(ex); } }
public void UpdateActualVersionForSolution() { ActualVersionForSolution.SetValue(GetActualVersionForSolution()); }