예제 #1
0
        public ConnectionTracker(Lifetime lifetime, ILogger logger, UnityHost host, UnityEditorProtocol unityEditorProtocolController, IShellLocks locks)
        {
            // TODO: this shouldn't be up in tests until we figure out how to test unity-editor requiring features
            if (locks.Dispatcher.IsAsyncBehaviorProhibited)
            {
                return;
            }

            //check connection between backend and unity editor
            locks.QueueRecurring(lifetime, "PeriodicallyCheck", TimeSpan.FromSeconds(1), () =>
            {
                if (unityEditorProtocolController.UnityModel.Value == null)
                {
                    myLastCheckResult = UnityEditorState.Disconnected;
                }
                else
                {
                    var rdTask = unityEditorProtocolController.UnityModel.Value.GetUnityEditorState.Start(RdVoid.Instance);
                    rdTask?.Result.Advise(lifetime, result =>
                    {
                        myLastCheckResult = result.Result;
                        logger.Trace($"myIsConnected = {myLastCheckResult}");
                    });
                }

                logger.Trace($"Sending connection state. State: {myLastCheckResult}");
                host.SetModelData("UNITY_EditorState", Wrap(myLastCheckResult));
            });
        }
        public void OnSolutionLoaded(UnityProjectsCollection solution)
        {
            var entry = myBoundStore.Schema.GetScalarEntry((UnitySettings s) => s.EnableShaderLabHippieCompletion);

            myBoundStore.GetValueProperty <bool>(myLifetime, entry, null).Change.Advise(myLifetime, pcea =>
            {
                if (pcea.HasNew)
                {
                    myHost.SetModelData("UNITY_SETTINGS_EnableShaderLabHippieCompletion", pcea.New.ToString());
                }
            });
        }
        private void CreateProtocol(FileSystemPath protocolInstancePath)
        {
            if (!protocolInstancePath.ExistsFile)
            {
                return;
            }

            int port;

            try
            {
                var protocolInstance = JsonConvert.DeserializeObject <ProtocolInstance>(protocolInstancePath.ReadAllText2().Text);
                port = protocolInstance.port_id;
            }
            catch (Exception e)
            {
                myLogger.Warn($"Unable to parse {protocolInstancePath}" + Environment.NewLine + e);
                return;
            }

            myLogger.Info($"UNITY_Port {port}.");

            try
            {
                var lifetime = mySessionLifetimes.Next();
                myLogger.Info("Create protocol...");

                myLogger.Info("Creating SocketWire with port = {0}", port);
                var wire = new SocketWire.Client(lifetime, myDispatcher, port, "UnityClient");
                wire.Connected.WhenTrue(lifetime, lf =>
                {
                    myLogger.Info("WireConnected.");
                    myHost.SetModelData("UNITY_Play", "undef");

                    var protocol = new Protocol("UnityEditorPlugin", new Serializers(), new Identities(IdKind.Client), myDispatcher, wire);
                    var model    = new EditorPluginModel(lf, protocol);
                    model.IsBackendConnected.Set(rdVoid => true);
                    model.RiderProcessId.SetValue(Process.GetCurrentProcess().Id);
                    myHost.SetModelData("UNITY_SessionInitialized", "true");

                    SubscribeToLogs(lf, model);
                    SubscribeToOpenFile(model);
                    model.Play.AdviseNotNull(lf, b => myHost.SetModelData("UNITY_Play", b.ToString().ToLower()));
                    model.Pause.AdviseNotNull(lf, b => myHost.SetModelData("UNITY_Pause", b.ToString().ToLower()));

                    BindPluginPathToSettings(lf, model);

                    TrackActivity(model, lf);

                    if (!myComponentLifetime.IsTerminated)
                    {
                        myLocks.ExecuteOrQueueEx(myComponentLifetime, "setModel", () => { myUnityModel.SetValue(model, myReadonlyToken); });
                    }

                    lf.AddAction(() =>
                    {
                        if (!myComponentLifetime.IsTerminated)
                        {
                            myLocks.ExecuteOrQueueEx(myComponentLifetime, "clearModel", () =>
                            {
                                myLogger.Info("Wire disconnected.");
                                myHost.SetModelData("UNITY_SessionInitialized", "false");
                                myUnityModel.SetValue(null, myReadonlyToken);
                            });
                        }
                    });
                });
            }
            catch (Exception ex)
            {
                myLogger.Error(ex);
            }
        }
        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($"UNITY_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);
                    var model = new EditorPluginModel(lf, protocol);
                    model.IsBackendConnected.Set(rdVoid => true);
                    var frontendProcess = Process.GetCurrentProcess().GetParent();
                    if (frontendProcess != null)
                    {
                        model.RiderProcessId.SetValue(frontendProcess.Id);
                    }

                    myHost.SetModelData("UNITY_SessionInitialized", "true");

                    SubscribeToLogs(lf, model);
                    SubscribeToOpenFile(model);
                    model.Play.AdviseNotNull(lf, b => myHost.PerformModelAction(a => a.Play.SetValue(b)));
                    model.Pause.AdviseNotNull(lf, b => myHost.SetModelData("UNITY_Pause", b.ToString().ToLower()));

                    // 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
                    model.EditorLogPath.Advise(lifetime,
                                               s => myHost.PerformModelAction(a => a.EditorLogPath.SetValue(s)));
                    model.PlayerLogPath.Advise(lifetime,
                                               s => myHost.PerformModelAction(a => a.PlayerLogPath.SetValue(s)));

                    model.ApplicationPath.Advise(lifetime,
                                                 s => myHost.PerformModelAction(a => a.ApplicationPath.SetValue(s)));
                    model.ApplicationContentsPath.Advise(lifetime,
                                                         s => myHost.PerformModelAction(a => a.ApplicationContentsPath.SetValue(s)));

                    BindPluginPathToSettings(lf, model);

                    TrackActivity(model, lf);

                    if (!myComponentLifetime.IsTerminated)
                    {
                        myLocks.ExecuteOrQueueEx(myComponentLifetime, "setModel",
                                                 () => { myUnityModel.SetValue(model, myReadonlyToken); });
                    }

                    lf.AddAction(() =>
                    {
                        if (!myComponentLifetime.IsTerminated)
                        {
                            myLocks.ExecuteOrQueueEx(myComponentLifetime, "clearModel", () =>
                            {
                                myLogger.Info("Wire disconnected.");
                                myHost.SetModelData("UNITY_SessionInitialized", "false");
                                myUnityModel.SetValue(null, myReadonlyToken);
                            });
                        }
                    });
                });
            }
            catch (Exception ex)
            {
                myLogger.Error(ex);
            }
        }