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); }); }); }
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)); }