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