public void OnCompilationDone(VSGraphModel vsGraphModel, CompilationOptions options, CompilationResult results) { if (!this) { // Should not happen, but it did, so... Debug.LogWarning("A destroyed VseWindow still has an OnCompilationDone callback registered."); return; } State state = m_Store.GetState(); VseUtility.UpdateCodeViewer(show: false, sourceIndex: SourceCodePhases.Initial, compilationResult: results, selectionDelegate: lineMetadata => { if (lineMetadata == null) { return; } GUID nodeGuid = (GUID)lineMetadata; m_Store.Dispatch(new PanToNodeAction(nodeGuid)); }); //TODO: incremental re-register m_PluginRepository.RegisterPlugins(options); UpdateCompilationErrorsDisplay(state); if (results != null && results.errors.Count == 0) { // TODO : Add delegate to register to compilation Done // VSCompilationService.NotifyChange((ISourceProvider)vsGraphModel.assetModel); } }
public TokenDeclaration(Store store, IVariableDeclarationModel model, GraphView graphView) { m_Pill = new Pill(); Add(m_Pill); if (model is IObjectReference modelReference) { if (modelReference is IExposeTitleProperty titleProperty) { #if UNITY_2019_3_OR_NEWER m_TitleLabel = m_Pill.Q <Label>("title-label"); #else m_TitleLabel = m_Pill.Q <Label>("title-label").ReplaceWithBoundLabel(); #endif m_TitleLabel.bindingPath = titleProperty.TitlePropertyName; } } RegisterCallback <AttachToPanelEvent>(OnAttachToPanel); RegisterCallback <DetachFromPanelEvent>(OnDetachFromPanel); styleSheets.Add(AssetDatabase.LoadAssetAtPath <StyleSheet>(UICreationHelper.templatePath + "Token.uss")); Declaration = model; m_Store = store; m_GraphView = graphView; m_Pill.icon = Declaration.IsExposed ? VisualScriptingIconUtility.LoadIconRequired("GraphView/Nodes/BlackboardFieldExposed.png") : null; m_Pill.text = Declaration.Title; if (model != null) { capabilities = VseUtility.ConvertCapabilities(model); } var variableModel = model as VariableDeclarationModel; Stencil stencil = store.GetState().CurrentGraphModel?.Stencil; if (variableModel != null && stencil && variableModel.DataType.IsValid) { string friendlyTypeName = variableModel.DataType.GetMetadata(stencil).FriendlyName; Assert.IsTrue(!string.IsNullOrEmpty(friendlyTypeName)); tooltip = $"{variableModel.VariableString} declaration of type {friendlyTypeName}"; if (!string.IsNullOrEmpty(variableModel.Tooltip)) { tooltip += "\n" + variableModel.Tooltip; } } SetClasses(); this.EnableRename(); if (model != null) { viewDataKey = model.GetId(); } }
public void DisplayCompilationErrors(State state) { VseUtility.RemoveLogEntries(); if (ModelsToNodeMapping == null) { UpdateTopology(); } var lastCompilationResult = state.CompilationResultModel.GetLastResult(); if (lastCompilationResult?.errors == null) { return; } foreach (var error in lastCompilationResult.errors) { if (error.sourceNode != null && !error.sourceNode.Destroyed) { var alignment = error.sourceNode is IStackModel ? SpriteAlignment.TopCenter : SpriteAlignment.RightCenter; ModelsToNodeMapping.TryGetValue(error.sourceNode, out var graphElement); if (graphElement != null) { AttachErrorBadge(graphElement, error.description, alignment, m_Store, error.quickFix); } } var graphAsset = (GraphAssetModel)m_Store.GetState().CurrentGraphModel?.AssetModel; var graphAssetPath = graphAsset ? AssetDatabase.GetAssetPath(graphAsset) : "<unknown>"; VseUtility.LogSticky(error.isWarning ? LogType.Warning : LogType.Error, LogOption.None, $"{graphAssetPath}: {error.description}", $"{graphAssetPath}@{error.sourceNodeGuid}", graphAsset.GetInstanceID()); } }
public static void CreateGraphAsset <TStencilType>(string graphAssetName = k_DefaultGraphAssetName) where TStencilType : Stencil { string uniqueFilePath = VseUtility.GetUniqueAssetPathNameInActiveFolder(graphAssetName); string modelName = Path.GetFileName(uniqueFilePath); var endAction = CreateInstance <DoCreateVisualScriptAsset>(); endAction.StencilType = typeof(TStencilType); ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, endAction, modelName, GetIcon(), null); }
public Edge(IEdgeModel edgeModel) : this() { m_EdgeModel = edgeModel; capabilities = VseUtility.ConvertCapabilities(m_EdgeModel); PortType portType = m_EdgeModel?.OutputPortModel?.PortType ?? PortType.Data; EnableInClassList("execution", portType == PortType.Execution || portType == PortType.Loop); EnableInClassList("event", portType == PortType.Event); viewDataKey = m_EdgeModel?.GetId(); }
public TokenDeclaration Clone() { var clone = new TokenDeclaration(m_Store, Declaration, m_GraphView) { viewDataKey = Guid.NewGuid().ToString() }; if (Declaration is LoopVariableDeclarationModel loopVariableDeclarationModel) { VseUtility.AddTokenIcon(clone, loopVariableDeclarationModel.TitleComponentIcon); } return(clone); }
public Placemat(PlacematModel model, Store store, GraphView graphView) { m_Model = model; m_Store = store; base.SetPosition(model.Position); base.Color = model.Color; base.title = model.Title; base.ZOrder = model.ZOrder; base.Collapsed = model.Collapsed; capabilities = VseUtility.ConvertCapabilities(model); }
void UpdateFromModel() { SetPosition(new Rect(stackModel.Position.x, stackModel.Position.y, 0, 0)); capabilities = VseUtility.ConvertCapabilities(stackModel); UpdatePortsFromModels(stackModel.InputPorts, "input"); UpdatePortsFromModels(stackModel.OutputPorts, "output"); viewDataKey = stackModel.GetId(); if (!stackModel.NodeModels.Any()) { var contentContainerPlaceholder = this.MandatoryQ("stackNodeContentContainerPlaceholder"); contentContainerPlaceholder.AddToClassList("empty"); } }
public static GraphElement CreateToken(this INodeBuilder builder, Store store, IVariableModel model) { var isExposed = model.DeclarationModel?.IsExposed; Texture2D icon = (isExposed != null && isExposed.Value) ? VisualScriptingIconUtility.LoadIconRequired("GraphView/Nodes/BlackboardFieldExposed.png") : null; GetTokenPorts(store, model, out var input, out var output, Orientation.Horizontal); var token = new Token(model, store, input, output, builder.GraphView, icon); if (model.DeclarationModel != null && model.DeclarationModel is LoopVariableDeclarationModel loopVariableDeclarationModel) { VseUtility.AddTokenIcon(token, loopVariableDeclarationModel.TitleComponentIcon); } return(token); }
void OnViewInCodeViewerButton() { var compilationResult = m_Store.GetState()?.CompilationResultModel?.GetLastResult(); if (compilationResult == null) { Debug.LogWarning("Compilation returned empty results"); return; } VseUtility.UpdateCodeViewer(show: true, sourceIndex: m_GraphView.window.ToggleCodeViewPhase, compilationResult: compilationResult, selectionDelegate: lineMetadata => { if (lineMetadata == null) { return; } GUID nodeGuid = (GUID)lineMetadata; m_Store.Dispatch(new PanToNodeAction(nodeGuid)); }); }
public void DisplayCompilationErrors(State state) { VseUtility.RemoveLogEntries(); if (ModelsToNodeMapping == null) { UpdateTopology(); } var lastCompilationResult = state.CompilationResultModel.GetLastResult(); if (lastCompilationResult?.errors == null) { return; } foreach (var error in lastCompilationResult.errors) { if (!(error.sourceNode.Model is INodeModel model)) { continue; } var alignment = model is IStackModel ? SpriteAlignment.TopCenter : SpriteAlignment.RightCenter; ModelsToNodeMapping.TryGetValue(model, out var graphElement); if (graphElement != null) { AttachErrorBadge(graphElement, error.description, alignment, m_Store, error.quickFix); } var graphAssetPath = AssetDatabase.GetAssetPath((GraphAssetModel)m_Store.GetState().CurrentGraphModel.AssetModel); VseUtility.LogSticky(LogType.Error, LogOption.None, $"{graphAssetPath}: {error.description}", graphAssetPath, error.sourceNodeId); } }
protected virtual void OnEnable() { if (m_PreviousGraphModels == null) { m_PreviousGraphModels = new List <GraphModel>(); } if (m_BlackboardExpandedRowStates == null) { m_BlackboardExpandedRowStates = new List <string>(); } if (m_ElementModelsToSelectUponCreation == null) { m_ElementModelsToSelectUponCreation = new List <string>(); } if (m_ElementModelsToExpandUponCreation == null) { m_ElementModelsToExpandUponCreation = new List <string>(); } rootVisualElement.RegisterCallback <ValidateCommandEvent>(OnValidateCommand); rootVisualElement.RegisterCallback <ExecuteCommandEvent>(OnExecuteCommand); rootVisualElement.RegisterCallback <MouseMoveEvent>(_ => m_IdleTimer?.Restart()); rootVisualElement.styleSheets.Add(AssetDatabase.LoadAssetAtPath <StyleSheet>(k_StyleSheetPath + "VSEditor.uss")); rootVisualElement.Clear(); rootVisualElement.style.overflow = Overflow.Hidden; rootVisualElement.pickingMode = PickingMode.Ignore; rootVisualElement.style.flexDirection = FlexDirection.Column; rootVisualElement.name = "vseRoot"; // Create the store. DataModel = CreateDataModel(); State initialState = CreateInitialState(); m_Store = new Store(initialState, Store.Options.TrackUndoRedo); VseUtility.SetupLogStickyCallback(); m_GraphContainer = new VisualElement { name = "graphContainer" }; m_GraphView = CreateGraphView(); m_Menu = CreateMenu(); m_BlankPage = CreateBlankPage(); IMGUIContainer imguiContainer = null; imguiContainer = new IMGUIContainer(() => { var timeRect = new Rect(0, 0, rootVisualElement.layout.width, imguiContainer.layout.height); m_TracingTimeline.OnGUI(timeRect); }); m_TracingTimeline = new TracingTimeline(m_Store.GetState(), imguiContainer); m_TracingTimeline.SyncVisible(); rootVisualElement.Add(m_Menu); rootVisualElement.Add(imguiContainer); rootVisualElement.Add(m_GraphContainer); m_CompilationPendingLabel = new Label("Compilation Pending") { name = "compilationPendingLabel" }; m_GraphContainer.Add(m_GraphView); m_ShortcutHandler = new ShortcutHandler( new Dictionary <Event, ShortcutDelegate> { { Event.KeyboardEvent("F2"), () => Application.platform != RuntimePlatform.OSXEditor ? RenameElement() : EventPropagation.Continue }, { Event.KeyboardEvent("F5"), () => { RefreshUI(UpdateFlags.All); return(EventPropagation.Continue); } }, { Event.KeyboardEvent("return"), () => Application.platform == RuntimePlatform.OSXEditor ? RenameElement() : EventPropagation.Continue }, { Event.KeyboardEvent("[enter]"), () => Application.platform == RuntimePlatform.OSXEditor ? RenameElement() : EventPropagation.Continue }, { Event.KeyboardEvent("backspace"), OnBackspaceKeyDown }, { Event.KeyboardEvent("space"), OnSpaceKeyDown }, { Event.KeyboardEvent("C"), () => { IGraphElementModel[] selectedModels = m_GraphView.selection .OfType <IHasGraphElementModel>() .Select(x => x.GraphElementModel) .ToArray(); // Convert variable -> constant if selection contains at least one item that satisfies conditions IVariableModel[] variableModels = selectedModels.OfType <VariableNodeModel>().Cast <IVariableModel>().ToArray(); if (variableModels.Any()) { m_Store.Dispatch(new ConvertVariableNodesToConstantNodesAction(variableModels)); return(EventPropagation.Stop); } IConstantNodeModel[] constantModels = selectedModels.OfType <IConstantNodeModel>().ToArray(); if (constantModels.Any()) { m_Store.Dispatch(new ConvertConstantNodesToVariableNodesAction(constantModels)); } return(EventPropagation.Stop); } }, { Event.KeyboardEvent("Q"), () => m_GraphView.AlignSelection(false) }, { Event.KeyboardEvent("#Q"), () => m_GraphView.AlignSelection(true) }, // DEBUG { Event.KeyboardEvent("1"), () => OnCreateLogNode(LogNodeModel.LogTypes.Message) }, { Event.KeyboardEvent("2"), () => OnCreateLogNode(LogNodeModel.LogTypes.Warning) }, { Event.KeyboardEvent("3"), () => OnCreateLogNode(LogNodeModel.LogTypes.Error) }, { Event.KeyboardEvent("`"), () => OnCreateStickyNote(new Rect(m_GraphView.ChangeCoordinatesTo(m_GraphView.contentViewContainer, m_GraphView.WorldToLocal(Event.current.mousePosition)), StickyNote.defaultSize)) }, }); rootVisualElement.parent.AddManipulator(m_ShortcutHandler); Selection.selectionChanged += OnGlobalSelectionChange; m_Store.StateChanged += StoreOnStateChanged; Undo.undoRedoPerformed += UndoRedoPerformed; rootVisualElement.RegisterCallback <AttachToPanelEvent>(OnEnterPanel); rootVisualElement.RegisterCallback <DetachFromPanelEvent>(OnLeavePanel); titleContent = new GUIContent("Visual Script"); // After a domain reload, all loaded objects will get reloaded and their OnEnable() called again // It looks like all loaded objects are put in a deserialization/OnEnable() queue // the previous graph's nodes/edges/... might be queued AFTER this window's OnEnable // so relying on objects to be loaded/initialized is not safe // hence, we need to defer the loading action rootVisualElement.schedule.Execute(() => { if (!String.IsNullOrEmpty(LastGraphFilePath)) { try { m_Store.Dispatch(new LoadGraphAssetAction(LastGraphFilePath, loadType: LoadGraphAssetAction.Type.KeepHistory)); } catch (Exception e) { Debug.LogError(e); } } else // will display the blank page. not needed otherwise as the LoadGraphAsset reducer will refresh { m_Store.Dispatch(new RefreshUIAction(UpdateFlags.All)); } }).ExecuteLater(0); m_LockTracker.lockStateChanged.AddListener(OnLockStateChanged); m_PluginRepository = new PluginRepository(m_Store, m_GraphView); EditorApplication.playModeStateChanged += OnEditorPlayModeStateChanged; EditorApplication.pauseStateChanged += OnEditorPauseStateChanged; if (DataModel is VSEditorDataModel vsDataModel) { vsDataModel.PluginRepository = m_PluginRepository; vsDataModel.OnCompilationRequest = OnCompilationRequest; } }
void OnOptionsButton() { GenericMenu menu = new GenericMenu(); VSGraphModel vsGraphModel = (VSGraphModel)m_Store.GetState().CurrentGraphModel; VSPreferences pref = m_Store.GetState().Preferences; void MenuItem(string title, bool value, GenericMenu.MenuFunction onToggle) => menu.AddItem(VseUtility.CreatTextContent(title), value, onToggle); void MenuToggle(string title, BoolPref k, Action callback = null) => MenuItem(title, pref.GetBool(k), () => { pref.ToggleBool(k); callback?.Invoke(); }); void MenuMapToggle(string title, Func <bool> match, GenericMenu.MenuFunction onToggle) => MenuItem(title, match(), onToggle); void MenuItemDisable(string title, bool value, GenericMenu.MenuFunction onToggle, Func <bool> shouldDisable) { if (shouldDisable()) { menu.AddDisabledItem(VseUtility.CreatTextContent(title)); } else { menu.AddItem(VseUtility.CreatTextContent(title), value, onToggle); } } MenuItem("Build All", false, AssetDatabase.SaveAssets); MenuItemDisable("Compile", false, () => { m_Store.GetState().EditorDataModel.RequestCompilation(RequestCompilationOptions.SaveGraph); }, () => (vsGraphModel == null || !vsGraphModel.Stencil.CreateTranslator().SupportsCompilation())); MenuItem("Auto-itemize/Variables", pref.CurrentItemizeOptions.HasFlag(ItemizeOptions.Variables), () => pref.ToggleItemizeOption(ItemizeOptions.Variables)); MenuItem("Auto-itemize/System Constants", pref.CurrentItemizeOptions.HasFlag(ItemizeOptions.SystemConstants), () => pref.ToggleItemizeOption(ItemizeOptions.SystemConstants)); MenuItem("Auto-itemize/Constants", pref.CurrentItemizeOptions.HasFlag(ItemizeOptions.Constants), () => pref.ToggleItemizeOption(ItemizeOptions.Constants)); MenuToggle("Show unused nodes", BoolPref.ShowUnusedNodes, () => m_Store.Dispatch(new RefreshUIAction(UpdateFlags.All))); if (Unsupported.IsDeveloperMode()) { MenuItem("Log compile time stats", LogCompileTimeStats, () => LogCompileTimeStats = !LogCompileTimeStats); MenuItem("Rebuild UI", false, () => { m_Store.Dispatch(new RefreshUIAction(UpdateFlags.All)); }); MenuItem("Rebuild Blackboard", false, () => { m_GraphView.UIController.Blackboard?.Rebuild(Blackboard.RebuildMode.BlackboardOnly); }); menu.AddSeparator(""); MenuItem("Reload and Rebuild UI", false, () => { if (m_Store.GetState()?.CurrentGraphModel != null) { var path = m_Store.GetState().CurrentGraphModel.GetAssetPath(); Selection.activeObject = null; Resources.UnloadAsset((Object)m_Store.GetState().CurrentGraphModel.AssetModel); Resources.UnloadAsset((Object)m_Store.GetState().CurrentGraphModel); m_Store.Dispatch(new LoadGraphAssetAction(path)); } }); MenuItem("Layout", false, () => { m_GraphView.FrameAll(); m_Store.Dispatch(new RefreshUIAction(UpdateFlags.All)); }); menu.AddSeparator(""); MenuItem("Clear Searcher Databases", false, () => { var provider = m_Store.GetState().CurrentGraphModel.Stencil.GetSearcherDatabaseProvider(); provider.ClearTypesItemsSearcherDatabases(); provider.ClearTypeMembersSearcherDatabases(); provider.ClearGraphElementsSearcherDatabases(); provider.ClearGraphVariablesSearcherDatabases(); provider.ClearReferenceItemsSearcherDatabases(); }); MenuItem("Integrity Check", false, () => vsGraphModel.CheckIntegrity(GraphModel.Verbosity.Verbose)); MenuItem("Graph cleanup", false, () => { vsGraphModel.QuickCleanup(); vsGraphModel.CheckIntegrity(GraphModel.Verbosity.Verbose); }); MenuItem("Fix and reimport all textures", false, OnFixAndReimportTextures); MenuToggle("Auto compilation when idle", BoolPref.AutoRecompile); MenuToggle("Auto align new dragged edges", BoolPref.AutoAlignDraggedEdges); if (Unsupported.IsDeveloperMode()) { MenuToggle("Bound object logging", BoolPref.BoundObjectLogging); MenuToggle("Dependencies logging", BoolPref.DependenciesLogging); MenuToggle("UI Performance/Always fully rebuild UI on change", BoolPref.FullUIRebuildOnChange); MenuToggle("UI Performance/Warn when UI gets fully rebuilt", BoolPref.WarnOnUIFullRebuild); MenuToggle("UI Performance/Log UI build time", BoolPref.LogUIBuildTime); if (DebugDisplayElement.Allowed) { MenuItem("Show Debug", m_GraphView.ShowDebug, () => m_GraphView.ShowDebug = !m_GraphView.ShowDebug); } MenuToggle("Diagnostics/Log Recursive Action Dispatch", BoolPref.ErrorOnRecursiveDispatch); MenuToggle("Diagnostics/Log Multiple Actions Dispatch", BoolPref.ErrorOnMultipleDispatchesPerFrame); MenuToggle("Diagnostics/Log All Dispatched Actions", BoolPref.LogAllDispatchedActions); MenuItem("Spawn all node types in graph", false, () => { VSGraphModel graph = (VSGraphModel)m_Store.GetState().CurrentGraphModel; Stencil stencil = graph.Stencil; Vector2 nextPosition = Vector2.zero; Vector2 spaceBetween = new Vector2(300, 0); foreach (var node in stencil.SpawnAllNodes(graph)) { node.Position += nextPosition; nextPosition += spaceBetween; } }); } var compilationResult = m_Store.GetState()?.CompilationResultModel?.GetLastResult(); if (compilationResult != null) { foreach (var pluginType in compilationResult.pluginSourceCode.Keys) { MenuMapToggle(title: "CodeViewer/Plugin/" + pluginType.Name, match: () => pref.PluginTypePref == pluginType, onToggle: () => { VseUtility.UpdateCodeViewer(show: true, pluginIndex: pluginType, compilationResult: compilationResult, selectionDelegate: lineMetadata => { if (lineMetadata == null) { return; } GUID nodeGuid = (GUID)lineMetadata; m_Store.Dispatch(new PanToNodeAction(nodeGuid)); }); pref.PluginTypePref = pluginType; }); } } } menu.ShowAsContext(); }
protected virtual void OnEnable() { if (m_PreviousGraphModels == null) { m_PreviousGraphModels = new List <OpenedGraph>(); } if (m_BlackboardExpandedRowStates == null) { m_BlackboardExpandedRowStates = new List <string>(); } if (m_ElementModelsToSelectUponCreation == null) { m_ElementModelsToSelectUponCreation = new List <string>(); } if (m_ElementModelsToExpandUponCreation == null) { m_ElementModelsToExpandUponCreation = new List <string>(); } rootVisualElement.RegisterCallback <ValidateCommandEvent>(OnValidateCommand); rootVisualElement.RegisterCallback <ExecuteCommandEvent>(OnExecuteCommand); rootVisualElement.RegisterCallback <MouseMoveEvent>(_ => m_IdleTimer?.Restart()); rootVisualElement.styleSheets.Add(AssetDatabase.LoadAssetAtPath <StyleSheet>(k_StyleSheetPath + "VSEditor.uss")); rootVisualElement.Clear(); rootVisualElement.style.overflow = Overflow.Hidden; rootVisualElement.pickingMode = PickingMode.Ignore; rootVisualElement.style.flexDirection = FlexDirection.Column; rootVisualElement.name = "vseRoot"; // Create the store. DataModel = CreateDataModel(); State initialState = CreateInitialState(); m_Store = new Store(initialState, Store.Options.TrackUndoRedo); VseUtility.SetupLogStickyCallback(); m_GraphContainer = new VisualElement { name = "graphContainer" }; m_GraphView = CreateGraphView(); m_Menu = CreateMenu(); m_BlankPage = CreateBlankPage(); SetupWindow(); m_CompilationPendingLabel = new Label("Compilation Pending") { name = "compilationPendingLabel" }; m_SidePanel = new VisualElement() { name = "sidePanel" }; m_ImguiContainer = new IMGUIContainer(DrawSidePanel) { name = "sidePanelInspector" }; m_SidePanel.Add(m_ImguiContainer); m_GraphContainer.Add(m_GraphView); m_GraphContainer.Add(m_SidePanel); Dictionary <Event, ShortcutDelegate> dictionaryShortcuts = GetShortcutDictionary(); m_ShortcutHandler = new ShortcutHandler(GetShortcutDictionary()); rootVisualElement.parent.AddManipulator(m_ShortcutHandler); m_Store.StateChanged += StoreOnStateChanged; Undo.undoRedoPerformed += UndoRedoPerformed; rootVisualElement.RegisterCallback <AttachToPanelEvent>(OnEnterPanel); rootVisualElement.RegisterCallback <DetachFromPanelEvent>(OnLeavePanel); // that will be true when the window is restored during the editor startup, so OnEnterPanel won't be called later if (rootVisualElement.panel != null) { OnEnterPanel(null); } titleContent = new GUIContent("Visual Script"); // After a domain reload, all loaded objects will get reloaded and their OnEnable() called again // It looks like all loaded objects are put in a deserialization/OnEnable() queue // the previous graph's nodes/edges/... might be queued AFTER this window's OnEnable // so relying on objects to be loaded/initialized is not safe // hence, we need to defer the loading action rootVisualElement.schedule.Execute(() => { if (!String.IsNullOrEmpty(LastGraphFilePath)) { try { m_Store.Dispatch(new LoadGraphAssetAction(LastGraphFilePath, boundObject: m_BoundObject, loadType: LoadGraphAssetAction.Type.KeepHistory)); } catch (Exception e) { Debug.LogError(e); } } else // will display the blank page. not needed otherwise as the LoadGraphAsset reducer will refresh { m_Store.Dispatch(new RefreshUIAction(UpdateFlags.All)); } }).ExecuteLater(0); m_LockTracker.lockStateChanged.AddListener(OnLockStateChanged); m_PluginRepository = new PluginRepository(m_Store, m_GraphView); EditorApplication.playModeStateChanged += OnEditorPlayModeStateChanged; EditorApplication.pauseStateChanged += OnEditorPauseStateChanged; if (DataModel is VSEditorDataModel vsDataModel) { vsDataModel.PluginRepository = m_PluginRepository; vsDataModel.OnCompilationRequest = OnCompilationRequest; } }