public static Port CreateInputPort(Store store, IPortModel inputPortModel, VisualElement instanceContainer, VisualElement dataContainer, VisualElement existingIcon = null, Orientation orientation = Orientation.Horizontal) { Assert.IsTrue(inputPortModel.Direction == Direction.Input, "Expected input port model"); var port = Create(inputPortModel, store, orientation, existingIcon); if (inputPortModel.PortType == PortType.Instance) { port.AddToClassList("instance"); instanceContainer.Insert(0, port); } else { VisualElement innerContainer = new VisualElement { name = "innerContainer" }; innerContainer.style.flexDirection = FlexDirection.Row; innerContainer.Add(port); dataContainer.Add(innerContainer); IConstantNodeModel modelToShow = port.GetModelToWatch(); if (modelToShow != null) { VisualElement editor = port.CreateEditorForNodeModel(modelToShow, _ => store.Dispatch(new RefreshUIAction(UpdateFlags.RequestCompilation))); if (editor != null) { innerContainer.Add(editor); port.m_InputEditor = editor; } } } return(port); }
public void AddItemRequested <TAction>(Store store, TAction _) where TAction : IAction { store.Dispatch(new CreateGraphVariableDeclarationAction(k_FieldName, true, typeof(float).GenerateTypeHandle(m_Stencil))); }
public void BuildContextualMenu() { var selectedModelsDictionary = m_Selection .OfType <IHasGraphElementModel>() .Where(x => !(x is BlackboardThisField)) // this blackboard field .Distinct(s_HasGraphElementModelComparer) .ToDictionary(x => x.GraphElementModel); IReadOnlyCollection <IGraphElementModel> selectedModelsKeys = selectedModelsDictionary.Keys.ToList(); BuildBlackboardContextualMenu(); var originatesFromBlackboard = (m_Evt.target as VisualElement)?.GetFirstOfType <Blackboard>() != null; if (!originatesFromBlackboard || m_Evt.target is IHasGraphElementModel) { BuildGraphViewContextualMenu(); if (!originatesFromBlackboard) { BuildNodeContextualMenu(selectedModelsDictionary); BuildStackContextualMenu(selectedModelsKeys); BuildEdgeContextualMenu(selectedModelsKeys); } BuildVariableNodeContextualMenu(selectedModelsKeys); if (!originatesFromBlackboard) { BuildConstantNodeContextualMenu(selectedModelsKeys); BuildStaticConstantNodeContextualMenu(selectedModelsKeys); BuildPropertyNodeContextualMenu(selectedModelsKeys); BuildSpecialContextualMenu(selectedModelsKeys); BuildStickyNoteContextualMenu(); BuildRefactorContextualMenu(selectedModelsKeys); } if (selectedModelsDictionary.Any()) { m_Evt.menu.AppendAction("Delete", menuAction => { m_Store.Dispatch(new DeleteElementsAction(selectedModelsKeys.ToArray())); }, eventBase => DropdownMenuAction.Status.Normal); } } if (originatesFromBlackboard && !(m_Evt.target is IHasGraphElementModel)) { var currentGraphModel = m_Store.GetState().CurrentGraphModel; currentGraphModel?.Stencil.GetBlackboardProvider() .BuildContextualMenu(m_Evt.menu, (VisualElement)m_Evt.target, m_Store, m_Evt.mousePosition); } var renamable = originatesFromBlackboard && m_Evt.target is IRenamable ? m_Evt.target as IRenamable : (!originatesFromBlackboard && selectedModelsDictionary.Count == 1) ? selectedModelsDictionary.Single().Value as IRenamable : null; if (renamable != null) { m_Evt.menu.AppendAction("Rename", menuAction => { renamable.Rename(true); m_Evt.PreventDefault(); m_Evt.StopImmediatePropagation(); }, eventBase => DropdownMenuAction.Status.Normal); } if (m_Evt.target is IContextualMenuBuilder contextualMenuBuilder) { contextualMenuBuilder.BuildContextualMenu(m_Evt); } }
void OnTypeChanged(TypeHandle handle) { m_Store.Dispatch(new UpdateTypeAction((VariableDeclarationModel)VariableDeclarationModel, handle)); RefreshUI(); }
protected 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 <ScriptableObject>(); } if (m_ElementModelsToActivateUponCreation == null) { m_ElementModelsToActivateUponCreation = new List <ScriptableObject>(); } if (m_ElementModelsToExpandUponCreation == null) { m_ElementModelsToExpandUponCreation = new List <ScriptableObject>(); } rootVisualElement.RegisterCallback <ValidateCommandEvent>(OnValidateCommand); rootVisualElement.RegisterCallback <ExecuteCommandEvent>(OnExecuteCommand); 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 = new VseGraphView(this, m_Store); m_Menu = CreateMenu(); m_Menu.OnToggleTracing += OnToggleTracing; m_BlankPage = new VseBlankPage(m_Store); rootVisualElement.Add(m_Menu); rootVisualElement.Add(m_GraphContainer); 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; } }