public static RdTask <T> ToRdTask <T>(this IRdTask <T> task, Lifetime lifetime) { if (task is RdTask <T> rdTask) { return(rdTask); } var newRdTask = new RdTask <T>(); task.Result.Advise(lifetime, result => { switch (result.Status) { case RdTaskStatus.Success: newRdTask.Set(result.Result); break; case RdTaskStatus.Canceled: newRdTask.SetCancelled(); break; case RdTaskStatus.Faulted: newRdTask.Set(result.Error); break; } }); return(newRdTask); }
private void SupportAbort(object runner) { var unityTestAssemblyRunnerField = runner.GetType().GetField("m_Runner", BindingFlags.Instance | BindingFlags.NonPublic); if (unityTestAssemblyRunnerField != null) { var unityTestAssemblyRunner = unityTestAssemblyRunnerField.GetValue(runner); var stopRunMethod = unityTestAssemblyRunner.GetType() .GetMethod("StopRun", BindingFlags.Instance | BindingFlags.Public); myLaunch.Abort.Set((lifetime, _) => { ourLogger.Verbose("Call StopRun method via reflection."); var task = new RdTask <bool>(); try { stopRunMethod.Invoke(unityTestAssemblyRunner, null); task.Set(true); } catch (Exception) { ourLogger.Verbose("Call StopRun method failed."); task.Set(false); } return(task); }); } }
public LambdaPsiHost(ISolution solution, ISymbolCache symbolCache, PsiIconManager psiIconManager, IconHost iconHost, ProjectModelViewHost projectModelViewHost, IShellLocks locks, ILogger logger) { _symbolCache = symbolCache; _psiIconManager = psiIconManager; _iconHost = iconHost; _projectModelViewHost = projectModelViewHost; _locks = locks; _logger = logger; var model = solution.GetProtocolSolution().GetLambdaPsiModel(); model.DetermineHandlers.Set((lifetime, unit) => { var task = new RdTask <List <HandlerCompletionItem> >(); task.Set(DetermineHandlers(solution)); return(task); }); model.IsHandlerExists.Set((lifetime, request) => { var task = new RdTask <bool>(); var className = request.ClassName; var methodName = request.MethodName; var projectId = request.ProjectId; var handlerExists = IsHandlerExists(lifetime, projectId, className, methodName); task.Set(handlerExists); return(task); }); }
private static void AdviseRefresh(EditorPluginModel model) { model.Refresh.Set((l, force) => { var task = new RdTask <Unit>(); ourLogger.Verbose("Refresh: SyncSolution Enqueue"); MainThreadDispatcher.Instance.Queue(() => { if (!EditorApplication.isPlaying && EditorPrefsWrapper.AutoRefresh || force != RefreshType.Normal) { if (force == RefreshType.ForceRequestScriptReload) { ourLogger.Verbose("Refresh: RequestScriptReload"); UnityEditorInternal.InternalEditorUtility.RequestScriptReload(); } ourLogger.Verbose("Refresh: SyncSolution Started"); UnityUtils.SyncSolution(); ourLogger.Verbose("Refresh: SyncSolution Completed"); } else { ourLogger.Verbose("AutoRefresh is disabled via Unity settings."); } task.Set(Unit.Instance); }); return(task); }); }
public override void OnWireReceived(UnsafeReader reader) { var taskId = RdId.Read(reader); var value = ReadRequestDelegate(SerializationContext, reader); if (LogReceived.IsTraceEnabled()) { LogReceived.Trace("endpoint `{0}`::({1}), taskId={2}, request = {3}", Location, RdId, taskId, value.PrintToString()); } RdTask <TRes> rdTask; using (UsingDebugInfo()) //now supports only sync handlers { try { rdTask = Handler(myBindLifetime, value); } catch (OperationCanceledException) { rdTask = RdTask <TRes> .Cancelled(); } catch (Exception e) { rdTask = RdTask <TRes> .Faulted(e); } } rdTask.Result.Advise(myBindLifetime, result => { if (LogSend.IsTraceEnabled()) { LogSend.Trace("endpoint `{0}`::({1}), taskId={2}, response = {3}", Location, RdId, taskId, result.PrintToString()); } RdTaskResult <TRes> validatedResult; try { if (result.Status == RdTaskStatus.Success) { AssertNullability(result.Result); } validatedResult = result; } catch (Exception e) { LogSend.Error(e); validatedResult = RdTaskResult <TRes> .Faulted(e); } Wire.Send(RdId, (writer) => { taskId.Write(writer); RdTaskResult <TRes> .Write(WriteResponseDelegate, SerializationContext, writer, validatedResult); }); }); }
public ProjectProtocolHandler(Lifetime lifetime, IProtocol protocol, ILogger logger) { logger.Log(LoggingLevel.INFO, $"{protocol.Name} is protocol"); BsmtRiderModel = new BSMT_RiderModel(lifetime, protocol); BSMT_RiderModel.RegisterDeclaredTypesSerializers(protocol.Serializers); BsmtRiderModel.FoundBeatSaberLocations .Set((t, _) => RdTask <string[]> .Successful(BeatSaberPathUtils.GetInstallDir().ToArray())); }
private static void AdviseRunMethod(EditorPluginModel model) { model.RunMethodInUnity.Set((lifetime, data) => { var task = new RdTask <RunMethodResult>(); MainThreadDispatcher.Instance.Queue(() => { if (!lifetime.IsAlive) { task.SetCancelled(); return; } try { ourLogger.Verbose($"Attempt to execute {data.MethodName}"); var assemblies = AppDomain.CurrentDomain.GetAssemblies(); var assembly = assemblies .FirstOrDefault(a => a.GetName().Name.Equals(data.AssemblyName)); if (assembly == null) { throw new Exception($"Could not find {data.AssemblyName} assembly in current AppDomain"); } var type = assembly.GetType(data.TypeName); if (type == null) { throw new Exception($"Could not find {data.TypeName} in assembly {data.AssemblyName}."); } var method = type.GetMethod(data.MethodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); if (method == null) { throw new Exception($"Could not find {data.MethodName} in type {data.TypeName}"); } try { method.Invoke(null, null); } catch (Exception e) { Debug.LogException(e); } task.Set(new RunMethodResult(true, string.Empty, string.Empty)); } catch (Exception e) { ourLogger.Log(LoggingLevel.WARN, $"Execute {data.MethodName} failed.", e); task.Set(new RunMethodResult(false, e.Message, e.StackTrace)); } }); return(task); }); }
protected override void Start() { Queue(() => { var demoModel = new DemoModel(ModelLifetime, Protocol); demoModel.Call.Set((lifetime, c) => RdTask <string> .Successful(c.ToString())); demoModel.Callback.Start("Csharp"); }); }
private static void AdviseRefresh(EditorPluginModel model) { model.Refresh.Set((l, force) => { var refreshTask = new RdTask <Unit>(); void SendResult() { if (!EditorApplication.isCompiling) { // ReSharper disable once DelegateSubtraction EditorApplication.update -= SendResult; ourLogger.Verbose("Refresh: SyncSolution Completed"); refreshTask.Set(Unit.Instance); } } ourLogger.Verbose("Refresh: SyncSolution Enqueue"); MainThreadDispatcher.Instance.Queue(() => { if (!EditorApplication.isPlaying && EditorPrefsWrapper.AutoRefresh || force != RefreshType.Normal) { try { if (force == RefreshType.ForceRequestScriptReload) { ourLogger.Verbose("Refresh: RequestScriptReload"); UnityEditorInternal.InternalEditorUtility.RequestScriptReload(); } ourLogger.Verbose("Refresh: SyncSolution Started"); UnityUtils.SyncSolution(); } catch (Exception e) { ourLogger.Error("Refresh failed with exception", e); } finally { EditorApplication.update += SendResult; } } else { refreshTask.Set(Unit.Instance); ourLogger.Verbose("AutoRefresh is disabled via Unity settings."); } }); return(refreshTask); }); }
public LambdaHost(ISolution solution, ISymbolCache symbolCache, PsiIconManager psiIconManager, IconHost iconHost) { _model = solution.GetProtocolSolution().GetLambdaModel(); _symbolCache = symbolCache; _psiIconManager = psiIconManager; _iconHost = iconHost; _model.DetermineHandlers.Set((lifetime, unit) => { var task = new RdTask <List <HandlerCompletionItem> >(); task.Set(DetermineHandlers(solution)); return(task); }); }
private void AdviseFrontendToUnityModel(Lifetime lifetime, FrontendBackendModel frontendBackendModel) { // BackendUnityModel is recreated frequently (e.g. on each AppDomain reload when changing play/edit mode). // So subscribe to the frontendBackendModel once and flow in changes only if backendUnityModel is available. // Note that we only flow changes, not the current value. Even though these properties are stateful, // frontendBackendModel is not the source of truth - values need to flow from backendUnityModel. Also, due // to model reload, we go through a few values before we stabilise. E.g.: // * User clicks play, fb.Play is true, flows into bu.Play which switches to play mode and causes an // AppDomain reload. // * bu.Play becomes false due to AppDomain teardown, flows into fb.Play // * BackendUnityModel is torn down and recreated (<- WARNING!) // * bu.Play becomes true as Unity enters play mode, flows into fb.Play // If we flowed the current value of fb.Play into backendUnityModel when it is recreated, we'd set it to // false, triggering play mode to end. // Step is simply since it's a non-stateful ISource<T> var backendUnityModelProperty = myBackendUnityHost.BackendUnityModel; frontendBackendModel.PlayControls.Play.FlowChangesIntoRdDeferred(lifetime, () => backendUnityModelProperty.Maybe.ValueOrDefault?.PlayControls.Play); frontendBackendModel.PlayControls.Pause.FlowChangesIntoRdDeferred(lifetime, () => backendUnityModelProperty.Maybe.ValueOrDefault?.PlayControls.Pause); frontendBackendModel.PlayControls.Step.Advise(lifetime, () => backendUnityModelProperty.Maybe.ValueOrDefault?.PlayControls.Step.Fire()); // Called from frontend to generate the UIElements schema files frontendBackendModel.GenerateUIElementsSchema.Set((l, u) => backendUnityModelProperty.Maybe.ValueOrDefault?.GenerateUIElementsSchema.Start(l, u).ToRdTask(l)); // Signalled from frontend to select and ping the object in the Project view frontendBackendModel.ShowFileInUnity.Advise(lifetime, file => backendUnityModelProperty.Maybe.ValueOrDefault?.ShowFileInUnity.Fire(file)); // Signalled from fronted to open the preferences window frontendBackendModel.ShowPreferences.Advise(lifetime, _ => backendUnityModelProperty.Maybe.ValueOrDefault?.ShowPreferences.Fire()); // Called from frontend to run a method in unity frontendBackendModel.RunMethodInUnity.Set((l, data) => { var backendUnityModel = backendUnityModelProperty.Maybe.ValueOrDefault; return(backendUnityModel == null ? RdTask <RunMethodResult> .Cancelled() : backendUnityModel.RunMethodInUnity.Start(l, data).ToRdTask(l)); }); frontendBackendModel.HasUnsavedScenes.Set((l, u) => backendUnityModelProperty.Maybe.ValueOrDefault?.HasUnsavedScenes.Start(l, u).ToRdTask(l)); }
private RdTask <RdProjectOutput> GetProjectOutputModel(Lifetime lifetime, RdGetProjectOutputArgs args) { var project = GetProject( VirtualFileSystemPath.Parse(args.ProjectFilePath, InteractionContext.SolutionContext)); var targetFramework = project.TargetFrameworkIds // Take .NET Core first, then .NET Framework, and then .NET Standard. The comparer below will hold this order. .OrderBy(tfm => (!tfm.IsNetCoreApp, !tfm.IsNetFramework, !tfm.IsNetStandard)) .First(); _logger.Trace("TFM selected for project {0}: {1}", args, targetFramework); var assemblyInfo = project.GetOutputAssemblyInfo(targetFramework).NotNull(); _logger.Trace("Assembly file path detected for project {0}: {1}", args, assemblyInfo.Location); return(RdTask <RdProjectOutput> .Successful( new RdProjectOutput( targetFramework.ToRdTargetFrameworkInfo(), assemblyInfo.Location.ToString()))); }
public void TestBindable() { ClientWire.AutoTransmitMode = true; ServerWire.AutoTransmitMode = true; var call1 = new RdCall <Unit, RdSignal <int> >(Serializers.ReadVoid, Serializers.WriteVoid, RdSignal <int> .Read, RdSignal <int> .Write); var call2 = new RdCall <Unit, RdSignal <int> >(Serializers.ReadVoid, Serializers.WriteVoid, RdSignal <int> .Read, RdSignal <int> .Write); var respSignal = new RdSignal <int>(); var endpointLfTerminated = false; call2.Set((endpointLf, _) => { endpointLf.OnTermination(() => endpointLfTerminated = true); return(RdTask <RdSignal <int> > .Successful(respSignal)); }); var serverEntity = BindToServer(LifetimeDefinition.Lifetime, call1, ourKey); var clientEntity = BindToClient(LifetimeDefinition.Lifetime, call2, ourKey); var ld = new LifetimeDefinition(); var lf = ld.Lifetime; var signal = call1.Start(lf, Unit.Instance).AsTask().GetOrWait(lf); var log = new List <int>(); signal.Advise(Lifetime.Eternal, v => { log.Add(v); Console.WriteLine(v); }); respSignal.Fire(1); respSignal.Fire(2); respSignal.Fire(3); ld.Terminate(); Assert.False(respSignal.IsBound); SpinWaitEx.SpinUntil(() => log.Count >= 3); Thread.Sleep(100); Assert.AreEqual(new [] { 1, 2, 3 }, log.ToArray()); Assert.True(endpointLfTerminated); }
private static void AdviseRefresh(EditorPluginModel model) { model.Refresh.Set((l, force) => { var task = new RdTask <RdVoid>(); MainThreadDispatcher.Instance.Queue(() => { if (!EditorApplication.isPlaying && EditorPrefsWrapper.AutoRefresh || force) { UnityUtils.SyncSolution(); } else { ourLogger.Verbose("AutoRefresh is disabled via Unity settings."); } task.Set(RdVoid.Instance); }); return(task); }); }
public void TestNullability() { ClientWire.AutoTransmitMode = true; ServerWire.AutoTransmitMode = true; var serverEntity = BindToServer(LifetimeDefinition.Lifetime, new RdCall <string, string>(), ourKey); var clientEntity = BindToClient(LifetimeDefinition.Lifetime, new RdEndpoint <string, string>(x => x.ToString()), ourKey); clientEntity.Reset((lf, req) => RdTask <string> .Successful(req == null ? "NULL" : null)); Assert.Throws <Assertion.AssertionException>(() => { serverEntity.Sync(null); }); Assert.Throws <Assertion.AssertionException>(() => { using (Log.UsingLogFactory(new TestThrowingLogFactory())) { var task = serverEntity.Start("Value"); Assert.AreEqual(RdTaskStatus.Faulted, task.Result.Value.Status); } }); }
private RdTask <RdProjectOutput> GetProjectOutputModel(Lifetime lifetime, RdGetProjectOutputArgs args) { var projectsHostContainer = _solution.ProjectsHostContainer(); var solutionStructureContainer = projectsHostContainer.GetComponent <ISolutionStructureContainer>(); var projectMark = solutionStructureContainer .GetProjectsByLocation(FileSystemPath.Parse(args.ProjectFilePath)) .First(); var project = _solution.GetProjectByMark(projectMark).NotNull(); var targetFramework = project.TargetFrameworkIds // Take .NET Core first, then .NET Framework, and then .NET Standard. The comparer below will hold this order. .OrderBy(tfm => (!tfm.IsNetCoreApp, !tfm.IsNetFramework, !tfm.IsNetStandard)) .First(); _logger.Trace("TFM selected for project {0}: {1}", args, targetFramework); var assemblyInfo = project.GetOutputAssemblyInfo(targetFramework).NotNull(); _logger.Trace("Assembly file path detected for project {0}: {1}", args, assemblyInfo.Location); return(RdTask <RdProjectOutput> .Successful( new RdProjectOutput(targetFramework.Name, assemblyInfo.Location.ToString()))); }
private static void AdviseExitUnity(EditorPluginModel model) { model.ExitUnity.Set((_, rdVoid) => { var task = new RdTask <bool>(); MainThreadDispatcher.Instance.Queue(() => { try { ourLogger.Verbose("ExitUnity: Started"); EditorApplication.Exit(0); ourLogger.Verbose("ExitUnity: Completed"); task.Set(true); } catch (Exception e) { ourLogger.Log(LoggingLevel.WARN, "EditorApplication.Exit failed.", e); task.Set(false); } }); return(task); }); }
public AwsProjectHost(ISolution solution) { var model = solution.GetProtocolSolution().GetAwsProjectModel(); model.GetProjectOutput.Set((lifetime, request) => { var task = new RdTask <AwsProjectOutput>(); var assemblyPathPrefix = FileSystemPath.Parse(request.ProjectPath); using (ReadLockCookie.Create()) { var allProjects = solution.GetAllProjects(); foreach (var project in allProjects) { var targetFrameworks = project.GetAllTargetFrameworks(); foreach (var targetFramework in targetFrameworks) { var assembly = project.GetOutputAssemblyInfo(targetFramework.FrameworkId); if (assembly == null) { continue; } if (assembly.Location.FullPath.StartsWith(assemblyPathPrefix.FullPath)) { task.Set(new AwsProjectOutput(assembly.AssemblyNameInfo.Name, assembly.Location.FullPath)); return(task); } } } task.SetCancelled(); return(task); } }); }
private static UnityModel CreateModel(Protocol protocol, Lifetime lt) { var isPlayingAction = new Action(() => { MainThreadDispatcher.Instance.Queue(() => { var isPlaying = EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying; ourModel?.Maybe.ValueOrDefault?.Play.SetValue(isPlaying); var isPaused = EditorApplication.isPaused; ourModel?.Maybe.ValueOrDefault?.Pause.SetValue(isPaused); }); }); var model = new UnityModel(lt, protocol); isPlayingAction(); // get Unity state model.Play.Advise(lt, play => { MainThreadDispatcher.Instance.Queue(() => { var res = EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying; if (res != play) { EditorApplication.isPlaying = play; } }); }); model.Pause.Advise(lt, pause => { MainThreadDispatcher.Instance.Queue(() => { EditorApplication.isPaused = pause; }); }); model.LogModelInitialized.SetValue(new UnityLogModelInitialized()); model.Refresh.Set((l, force) => { var task = new RdTask <RdVoid>(); MainThreadDispatcher.Instance.Queue(() => { if (EditorPrefsWrapper.AutoRefresh || force) { UnityUtils.SyncSolution(); } else { ourLogger.Verbose("AutoRefresh is disabled via Unity settings."); } task.Set(RdVoid.Instance); }); return(task); }); model.Step.Set((l, x) => { var task = new RdTask <RdVoid>(); MainThreadDispatcher.Instance.Queue(() => { EditorApplication.Step(); task.Set(RdVoid.Instance); }); return(task); }); var isPlayingHandler = new EditorApplication.CallbackFunction(() => isPlayingAction()); // left for compatibility with Unity <= 5.5 #pragma warning disable 618 lt.AddBracket(() => { EditorApplication.playmodeStateChanged += isPlayingHandler; }, () => { EditorApplication.playmodeStateChanged -= isPlayingHandler; }); #pragma warning restore 618 //isPlayingHandler(); // new api - not present in Unity 5.5 //lt.AddBracket(() => { EditorApplication.pauseStateChanged+= IsPauseStateChanged(model);}, // () => { EditorApplication.pauseStateChanged -= IsPauseStateChanged(model); }); ourLogger.Verbose("CreateModel finished."); return(model); }
public void Set(Func <TReq, TRes> handler) { Set((lf, req) => RdTask <TRes> .Successful(handler(req))); }
internal static void SupportAbortNew(UnitTestLaunch launch) { try { const string assemblyName = "UnityEditor.TestRunner"; const string typeName = "UnityEditor.TestTools.TestRunner.Api.TestRunnerApi"; const string methodName = "CancelAllTestRuns"; MethodInfo stopRunMethod = null; var assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name.Equals(assemblyName)); if (assembly == null) { ourLogger.Verbose($"Could not find {assemblyName} in the AppDomain."); } else { var apiType = assembly.GetType(typeName); if (apiType == null) { ourLogger.Verbose($"Could not find {typeName} in the {assemblyName}."); } else { stopRunMethod = apiType.GetMethod(methodName); if (stopRunMethod == null) { ourLogger.Verbose($"Could not find {methodName} in the {typeName}."); } } } launch.Abort.Set((lifetime, _) => { var task = new RdTask <bool>(); if (stopRunMethod != null) { ourLogger.Verbose($"Call {methodName} method via reflection."); try { stopRunMethod.Invoke(null, null); task.Set(true); if (!launch.RunStarted.HasTrueValue()) // if RunStarted never happened { launch.RunResult(new RunResult(false)); } } catch (Exception) { ourLogger.Verbose($"Call {methodName} method failed."); task.Set(false); } } else { task.Set(false); } return(task); }); } catch (Exception e) { ourLogger.Error(e, "Unexpected exception in SupportAbortNew"); } }
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"); UnityWire.Value = wire; wire.BackwardsCompatibleWireFormat = true; 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.ActualVersionForSolution.Value; 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.LastPlayTime.Advise(lf, time => myHost.PerformModelAction(rd => rd.LastPlayTime.SetValue(time))); editor.LastInitTime.Advise(lf, time => myHost.PerformModelAction(rd => rd.LastInitTime.SetValue(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)); }); editor.BuildLocation.Advise(lf, b => myHost.PerformModelAction(rd => rd.BuildLocation.SetValue(b))); myHost.PerformModelAction(rd => { rd.RunMethodInUnity.Set((l, data) => { var editorRdTask = editor.RunMethodInUnity.Start(l, new RunMethodData(data.AssemblyName, data.TypeName, data.MethodName)).ToRdTask(l); var frontendRes = new RdTask <JetBrains.Rider.Model.RunMethodResult>(); editorRdTask.Result.Advise(l, r => { frontendRes.Set(new JetBrains.Rider.Model.RunMethodResult(r.Result.Success, r.Result.Message, r.Result.StackTrace)); }); return(frontendRes); }); }); 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 RdEndpoint(Func <TReq, TRes> handler) : this((lf, req) => RdTask <TRes> .Successful(handler(req))) { }
private static void AdviseUnityActions(EditorPluginModel model, Lifetime connectionLifetime) { var isPlayingAction = new Action(() => { MainThreadDispatcher.Instance.Queue(() => { var isPlayOrWillChange = EditorApplication.isPlayingOrWillChangePlaymode; var isPlaying = isPlayOrWillChange && EditorApplication.isPlaying; if (!model.Play.HasValue() || model.Play.HasValue() && model.Play.Value != isPlaying) { model.Play.SetValue(isPlaying); } var isPaused = EditorApplication.isPaused; if (!model.Pause.HasValue() || model.Pause.HasValue() && model.Pause.Value != isPaused) { model.Pause.SetValue(isPaused); } }); }); isPlayingAction(); // get Unity state model.Play.Advise(connectionLifetime, play => { MainThreadDispatcher.Instance.Queue(() => { var res = EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying; if (res != play) { EditorApplication.isPlaying = play; } }); }); model.Pause.Advise(connectionLifetime, pause => { MainThreadDispatcher.Instance.Queue(() => { EditorApplication.isPaused = pause; }); }); model.Step.Set((l, x) => { var task = new RdTask <RdVoid>(); MainThreadDispatcher.Instance.Queue(() => { EditorApplication.Step(); task.Set(RdVoid.Instance); }); return(task); }); var isPlayingHandler = new EditorApplication.CallbackFunction(() => isPlayingAction()); // left for compatibility with Unity <= 5.5 #pragma warning disable 618 connectionLifetime.AddBracket(() => { EditorApplication.playmodeStateChanged += isPlayingHandler; }, () => { EditorApplication.playmodeStateChanged -= isPlayingHandler; }); #pragma warning restore 618 // new api - not present in Unity 5.5 // private static Action<PauseState> IsPauseStateChanged(UnityModel model) // { // return state => model?.Pause.SetValue(state == PauseState.Paused); // } }
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); }); } }
public T4TestHost( [NotNull] T4TestModel model, [NotNull] SolutionsManager solutionsManager ) { model.PreprocessFile.Set(location => { using var cookie = ReadLockCookie.Create(); var solution = solutionsManager.Solution; if (solution == null) { return(Unit.Instance); } var host = solution.GetComponent <ProjectModelViewHost>(); var projectFile = host.GetItemById <IProjectFile>(location.Id).NotNull(); var sourceFile = projectFile.ToSourceFile().NotNull(); sourceFile.GetPsiServices().Files.CommitAllDocuments(); var file = sourceFile.GetPsiFiles(T4Language.Instance).OfType <IT4File>().SingleItem().NotNull(); var templatePreprocessingManager = solution.GetComponent <IT4TemplatePreprocessingManager>(); templatePreprocessingManager.Preprocess(file); return(Unit.Instance); }); model.WaitForIndirectInvalidation.Set((lifetime, unit) => { using var cookie = ReadLockCookie.Create(); var solution = solutionsManager.Solution; if (solution == null) { return(RdTask <Unit> .Successful(Unit.Instance)); } var cache = solution.GetComponent <T4FileDependencyCache>(); var result = new RdTask <Unit>(); void Requeue(int n) { if (n == 1) { result.Set(Unit.Instance); return; } solution.Locks.Queue(lifetime, "T4TestHost::.ctor::lambda::Requeue", () => { if (cache.HasDirtyFiles) { Commit(n - 1); } else { Requeue(n - 1); } }); } void Commit(int n) => solution.GetPsiServices().Files.ExecuteAfterCommitAllDocuments(() => Requeue(n)); // First commit applies all changes in files. // Then we re-queue the action to make sure that indirect invalidation happens, // then we commit the files again to apply the indirect changes // Commit(2) -> Requeue(2) -> Commit(1) -> Requeue(1) Commit(2); return(result); }); }