/// <inheritdoc /> protected override void BuildPartUI(VisualElement parent) { if (m_Model is IVariableDeclarationModel variableDeclarationModel) { m_Field = GraphElementFactory.CreateUI <GraphElement>(m_OwnerElement.View, m_OwnerElement.CommandDispatcher, variableDeclarationModel, blackboardVariablePartCreationContext); if (m_Field == null) { return; } m_Field.AddToClassList(ussClassName); m_Field.AddToClassList(m_ParentClassName.WithUssElement(PartName)); m_Field.viewDataKey = m_Model.Guid + "__" + Blackboard.persistenceKey; m_Field.AddToView(m_OwnerElement.View); if (m_Field is BlackboardField blackboardField) { blackboardField.NameLabel.RegisterCallback <ChangeEvent <string> >(OnFieldRenamed); } if (parent is BlackboardRow row) { row.FieldSlot.Add(m_Field); } else { parent.Add(m_Field); } } }
static bool WasSelectableDescendantHitByMouse(GraphElement currentTarget, MouseDownEvent evt) { VisualElement targetElement = evt.target as VisualElement; if (targetElement == null || currentTarget == targetElement) { return(false); } VisualElement descendant = targetElement; while (descendant != null && currentTarget != descendant) { GraphElement selectableDescendant = descendant as GraphElement; if (selectableDescendant != null && selectableDescendant.enabledInHierarchy && selectableDescendant.pickingMode != PickingMode.Ignore && selectableDescendant.Model.IsSelectable()) { Vector2 localMousePosition = currentTarget.ChangeCoordinatesTo(descendant, evt.localMousePosition); if (selectableDescendant.ContainsPoint(localMousePosition)) { return(true); } } descendant = descendant.parent; } return(false); }
internal void BeginSnap(GraphElement selectedElement) { UpdateSnappingStrategies(); foreach (var snapStrategy in m_SnappingStrategies.Where(snapStrategy => snapStrategy.Enabled)) { snapStrategy.BeginSnap(selectedElement); } }
static void OffsetDependency(GraphElement element, IDependency model, Vector2 delta, INodeModel _) { Vector2 prevPos = model.DependentNode.Position; Rect posRect = element.GetPosition(); posRect.position = prevPos + delta; element.SetPosition(posRect); }
void UpdateSpacingPositions(GraphElement selectedElement, Rect sourceRect) { ClearRectsToConsider(); GetRectsToConsiderInView(selectedElement); SortReferenceRects(); ComputeSpacingPositions(m_VerticalReferenceRects, sourceRect); ComputeSpacingPositions(m_HorizontalReferenceRects, sourceRect); }
static void AdjustSnappedRect(ref Rect snappedRect, Rect sourceRect, GraphElement selectedElement, float scale, SnapStrategy snapStrategy, Vector2 mousePanningDelta = default) { // Retrieve the snapping strategy's suggested snapped rect and its snapping offset Vector2 snappingOffset = new Vector2(float.MaxValue, float.MaxValue); Rect suggestedSnappedRect = snapStrategy.GetSnappedRect(ref snappingOffset, sourceRect, selectedElement, scale, mousePanningDelta); // Set snapped rect coordinates using the suggested rect's relevant coordinates SetSnappedRect(ref snappedRect, suggestedSnappedRect, snappingOffset); }
/// <summary> /// Callback for the MouseDown event. /// </summary> /// <param name="e">The event.</param> protected void OnMouseDown(MouseDownEvent e) { if (m_Active) { e.StopImmediatePropagation(); return; } m_Active = false; m_Dragging = false; m_AddedByMouseDown = false; if (target == null) { return; } m_SelectionContainer = target.GetFirstAncestorOfType <IDragSource>(); if (m_SelectionContainer == null) { // Keep for potential later use in OnMouseUp (where e.target might be different then) m_SelectionContainer = target.GetFirstOfType <IDragSource>(); m_SelectedElement = e.target as GraphElement; return; } m_SelectedElement = target.GetFirstOfType <GraphElement>(); if (m_SelectedElement == null) { return; } // Since we didn't drag after all, update selection with current element only if (!m_SelectedElement.IsSelected()) { var selectionMode = e.actionKey ? SelectElementsCommand.SelectionMode.Add : SelectElementsCommand.SelectionMode.Replace; m_SelectedElement.CommandDispatcher.Dispatch(new SelectElementsCommand(selectionMode, m_SelectedElement.Model)); m_AddedByMouseDown = true; } if (e.button == (int)m_ActivateButton) { // avoid starting a manipulation on a non movable object if (!m_SelectedElement.Model.IsDroppable()) { return; } m_MouseDownPosition = e.localMousePosition; m_Active = true; target.CaptureMouse(); e.StopPropagation(); } }
internal Rect GetSnappedRect(Rect sourceRect, GraphElement selectedElement, float scale, Vector2 mousePanningDelta = default) { Rect snappedRect = sourceRect; foreach (var snapStrategy in m_SnappingStrategies.Where(snapStrategy => snapStrategy.Enabled)) { AdjustSnappedRect(ref snappedRect, sourceRect, selectedElement, scale, snapStrategy, mousePanningDelta); } return(snappedRect); }
internal static BorderWidth GetBorderWidth(GraphElement element) { var borderWidth = new BorderWidth { Top = element.contentContainer.resolvedStyle.borderTopWidth, Bottom = element.contentContainer.resolvedStyle.borderBottomWidth, Left = element.contentContainer.resolvedStyle.borderLeftWidth, Right = element.contentContainer.resolvedStyle.borderRightWidth }; return(borderWidth); }
bool IsIgnoredElement(GraphElement selectedElement, GraphElement element, Rect rectToFit) { if (selectedElement is Placemat placemat && element.layout.Overlaps(placemat.layout) || element is Edge || !element.visible || element.IsSelected() || element.layout.Overlaps(selectedElement.layout)) { return(true); } Rect localSelRect = m_GraphView.ChangeCoordinatesTo(element, rectToFit); return(!element.Overlaps(localSelRect)); }
void AddReferenceRects(GraphElement selectedElement, GraphElement element, Rect rectToAdd) { // Check if element is within selectedElement's vertical boundaries before adding if (AreElementsSuperposed(selectedElement.layout, element.layout, PortOrientation.Horizontal)) { m_VerticalReferenceRects.Rects.Add(rectToAdd); } // Check if element is within selectedElement's horizontal boundaries before adding if (AreElementsSuperposed(selectedElement.layout, element.layout, PortOrientation.Vertical)) { m_HorizontalReferenceRects.Rects.Add(rectToAdd); } }
void GetLeftOversBoundingRects(ref List <Tuple <Rect, List <IGraphElementModel> > > boundingRects) { foreach (IGraphElementModel element in m_LeftOverElementModels) { GraphElement elementUI = element.GetUI <GraphElement>(m_GraphView); if (elementUI != null) { boundingRects.Add(new Tuple <Rect, List <IGraphElementModel> >(elementUI.GetPosition(), new List <IGraphElementModel> { element })); } } }
public override void BeginSnap(GraphElement selectedElement) { if (IsActive) { Debug.LogError("SnapService.BeginSnap: Snap to grid already active. Call EndSnap() first."); } IsActive = true; m_BorderWidth = GetBorderWidth(selectedElement); // Needed to snap element on its content container's border m_GraphView = selectedElement.GraphView; m_GridSpacing = m_GraphView.SafeQ <GridBackground>().Spacing; }
void SnapOrMoveElement(GraphElement element, Rect originalPos, Rect selectedElementGeom) { if (m_Snapper.IsActive) { Vector2 geomDiff = selectedElementGeom.position - m_OriginalPos[m_SelectedElement].pos.position; Vector2 position = new Vector2(originalPos.x + geomDiff.x, originalPos.y + geomDiff.y); element.SetPosition(new Rect(position, element.layout.size)); } else { MoveElement(element, originalPos); } }
void GetRectsToConsiderInView(GraphElement selectedElement) { // Consider only the visible nodes. Rect rectToFit = m_GraphView.layout; foreach (GraphElement element in m_GraphView.GraphElements.ToList()) { if (!IsIgnoredElement(selectedElement, element, rectToFit)) { Rect geometryInContentViewContainerSpace = (element).parent.ChangeCoordinatesTo(m_GraphView.ContentViewContainer, (element).GetPosition()); AddReferenceRects(selectedElement, element, geometryInContentViewContainerSpace); } } }
List <Rect> GetNotSelectedElementRectsInView(GraphElement selectedElement) { var notSelectedElementRects = new List <Rect>(); var ignoredModels = m_GraphView.GetSelection().ToList(); // Consider only the visible nodes. Rect rectToFit = m_GraphView.layout; foreach (GraphElement element in m_GraphView.GraphElements.ToList()) { if (selectedElement is Placemat placemat && element.layout.Overlaps(placemat.layout)) { // If the selected element is a placemat, we do not consider the elements under it ignoredModels.Add(element.Model); }
public override void BeginSnap(GraphElement selectedElement) { if (IsActive) { throw new InvalidOperationException("SnapStrategy.BeginSnap: Snap to spacing already active. Call EndSnap() first."); } IsActive = true; m_GraphView = selectedElement.GraphView; if (m_LineView == null) { m_LineView = new LineView(m_GraphView); } m_GraphView.Add(m_LineView); }
void MoveElement(GraphElement element, Rect originalPos) { Matrix4x4 g = element.worldTransform; var scale = new Vector3(g.m00, g.m11, g.m22); Rect newPos = new Rect(0, 0, originalPos.width, originalPos.height); // Compute the new position of the selected element using the mouse delta position and panning info newPos.x = originalPos.x - (m_MouseDiff.x - m_ItemPanDiff.x) * m_PanSpeed.x / scale.x * element.transform.scale.x; newPos.y = originalPos.y - (m_MouseDiff.y - m_ItemPanDiff.y) * m_PanSpeed.y / scale.y * element.transform.scale.y; newPos = m_GraphView.ContentViewContainer.ChangeCoordinatesTo(element.hierarchy.parent, newPos); element.SetPosition(newPos); }
public override void BeginSnap(GraphElement selectedElement) { if (IsActive) { throw new InvalidOperationException("SnapStrategy.BeginSnap: Snap to port already active. Call EndSnap() first."); } IsActive = true; if (selectedElement is Node selectedNode) { m_GraphView = selectedElement.GraphView; m_ConnectedEdges = GetConnectedEdges(selectedNode); m_ConnectedPortsPos = GetConnectedPortPositions(m_ConnectedEdges); } }
void ComputeSnappedRect(ref Rect selectedElementProposedGeom, GraphElement element) { // Check if snapping is paused first: if yes, the snapper will return the original dragging position if (Event.current != null) { m_Snapper.PauseSnap(Event.current.shift); } // Let the snapper compute a snapped position Rect geometryInContentViewContainerSpace = element.parent.ChangeCoordinatesTo(m_GraphView.ContentViewContainer, selectedElementProposedGeom); Vector2 mousePanningDelta = new Vector2((m_MouseDiff.x - m_ItemPanDiff.x) * m_PanSpeed.x / m_Scale, (m_MouseDiff.y - m_ItemPanDiff.y) * m_PanSpeed.y / m_Scale); geometryInContentViewContainerSpace = m_Snapper.GetSnappedRect(geometryInContentViewContainerSpace, element, m_Scale, mousePanningDelta); // Once the snapped position is computed in the GraphView.contentViewContainer's space then // translate it into the local space of the parent of the selected element. selectedElementProposedGeom = m_GraphView.ContentViewContainer.ChangeCoordinatesTo(element.parent, geometryInContentViewContainerSpace); }
protected void OnMouseUp(MouseUpEvent e) { GraphElement ce = e.target as GraphElement; if (ce != null && !ce.IsMovable()) { return; } if (m_Active) { if (CanStopManipulation(e)) { m_Active = false; target.ReleaseMouse(); e.StopPropagation(); } } }
/// <summary> /// Callback for the MouseCaptureOut event. /// </summary> /// <param name="e">The event.</param> protected void OnMouseCaptureOutEvent(MouseCaptureOutEvent e) { if (m_Active) { if (m_CurrentDropTarget != null && m_GraphView != null) { using (DragExitedEvent eExit = DragExitedEvent.GetPooled()) { eExit.target = m_CurrentDropTarget; m_GraphView.SendEvent(eExit); } } // Stop processing the event sequence if the target has lost focus, then. m_SelectedElement = null; m_CurrentDropTarget = null; m_Active = false; if (m_GraphView?.GetSelection().Any() ?? false) { m_Snapper.EndSnap(); } } }
public abstract void BeginSnap(GraphElement selectedElement);
/// <summary> /// Callback for the MouseUp event. /// </summary> /// <param name="evt">The event.</param> protected void OnMouseUp(MouseUpEvent evt) { if (m_GraphView == null) { if (m_Active) { target.ReleaseMouse(); m_SelectedElement = null; m_Active = false; m_Dragging = false; m_CurrentDropTarget = null; } return; } var selectedModels = m_GraphView.GetSelection(); if (CanStopManipulation(evt)) { if (m_Active) { if (m_Dragging || m_SelectedElement == null) { if (target is GraphView graphView) { graphView.StopSelectionDragger(); graphView.PositionDependenciesManager.StopNotifyMove(); } // if we stop dragging on something else than a DropTarget, just move elements if (m_GraphView != null && (m_CurrentDropTarget == null || !m_CurrentDropTarget.CanAcceptDrop(selectedModels))) { var movedElements = new HashSet <GraphElement>(m_OriginalPos.Keys); movedElements.AddRangeInternal(m_EdgesToUpdate); KeyValuePair <GraphElement, OriginalPos> firstPos = m_OriginalPos.First(); var delta = firstPos.Key.GetPosition().position - firstPos.Value.pos.position; var models = movedElements // PF remove this Where clause. It comes from VseGraphView.OnGraphViewChanged. .Where(e => !(e.Model is INodeModel) || e.IsMovable()) .Select(e => e.Model) .OfType <IMovable>(); m_GraphView.CommandDispatcher.Dispatch( new MoveElementsCommand(delta, models.ToList())); } } foreach (var edge in m_EdgesToUpdate) { edge.EdgeControl.ControlPointOffset = Vector2.zero; } m_EdgesToUpdate.Clear(); m_PanSchedule.Pause(); if (m_ItemPanDiff != Vector3.zero) { Vector3 p = m_GraphView.ContentViewContainer.transform.position; Vector3 s = m_GraphView.ContentViewContainer.transform.scale; m_GraphView.CommandDispatcher.Dispatch(new ReframeGraphViewCommand(p, s)); } if (selectedModels.Count > 0 && m_CurrentDropTarget != null) { if (m_CurrentDropTarget.CanAcceptDrop(selectedModels)) { using (DragPerformEvent ePerform = DragPerformEvent.GetPooled(evt)) { ePerform.target = m_CurrentDropTarget; m_GraphView.SendEvent(ePerform); } } else { using (DragExitedEvent eExit = DragExitedEvent.GetPooled(evt)) { eExit.target = m_CurrentDropTarget; m_GraphView.SendEvent(eExit); } } } if (selectedModels.Any()) { m_Snapper.EndSnap(); } target.ReleaseMouse(); evt.StopPropagation(); } m_SelectedElement = null; m_Active = false; m_CurrentDropTarget = null; m_Dragging = false; m_CurrentDropTarget = null; } }
static bool IsOnPlacemats(GraphElement element, List <Placemat> placemats) { return(placemats.Any(placemat => !element.Equals(placemat) && element.layout.Overlaps(placemat.layout))); }
public override Rect GetSnappedRect(ref Vector2 snappingOffset, Rect sourceRect, GraphElement selectedElement, float scale, Vector2 mousePanningDelta = default) { if (!IsActive) { throw new InvalidOperationException("SnapStrategy.GetSnappedRect: Snap to spacing not active. Call BeginSnap() first."); } if (IsPaused) { // Snapping was paused, we do not return a snapped rect and we clear the snap lines ClearSnapLines(); return(sourceRect); } Rect selectedElementRect = (selectedElement).parent.ChangeCoordinatesTo(m_GraphView.ContentViewContainer, (selectedElement).GetPosition()); UpdateSpacingPositions(selectedElement, selectedElementRect); Rect snappedRect = sourceRect; m_CurrentScale = scale; m_LineView.lines.Clear(); List <SnapToSpacingResult> results = GetClosestSpacingPositions(sourceRect); foreach (var result in results.Where(result => result != null)) { ApplySnapToSpacingResult(ref snappingOffset, sourceRect, ref snappedRect, result); // Make sure the element is snapped before drawing the lines if (IsSnapped(snappedRect, sourceRect, result.ReferenceRects.Orientation)) { foreach (SpacingLine spacingLine in GetSpacingLines(result.ReferenceRects.Rects, result.ReferenceRects.Orientation)) { m_LineView.lines.AddRange(spacingLine.Lines); } } } m_LineView.MarkDirtyRepaint(); return(snappedRect); }
/// <summary> /// Callback for the MouseMove event. /// </summary> /// <param name="e">The event.</param> protected void OnMouseMove(MouseMoveEvent e) { if (!m_Active) { return; } if (m_GraphView == null) { return; } var ve = (VisualElement)e.target; Vector2 gvMousePos = ve.ChangeCoordinatesTo(m_GraphView.contentContainer, e.localMousePosition); m_PanDiff = GetEffectivePanSpeed(gvMousePos); if (m_PanDiff != Vector3.zero) { m_PanSchedule.Resume(); } else { m_PanSchedule.Pause(); } // We need to monitor the mouse diff "by hand" because we stop positioning the graph elements once the // mouse has gone out. m_MouseDiff = m_OriginalMouse - e.mousePosition; if (m_SelectedElement.parent != null) { // Handle the selected element Rect selectedElementGeom = GetSelectedElementGeom(); ComputeSnappedRect(ref selectedElementGeom, m_SelectedElement); foreach (KeyValuePair <GraphElement, OriginalPos> v in m_OriginalPos) { GraphElement ce = v.Key; // Protect against stale visual elements that have been deparented since the start of the manipulation if (ce.hierarchy.parent == null) { continue; } if (!v.Value.dragStarted) { v.Value.dragStarted = true; } SnapOrMoveElement(v.Key, v.Value.pos, selectedElementGeom); } foreach (var edge in m_EdgesToUpdate) { SnapOrMoveEdge(edge, selectedElementGeom); } } var selection = m_GraphView.GetSelection(); var selectedUI = selection.Select(m => m.GetUI(m_GraphView)); // TODO: Replace with a temp drawing or something...maybe manipulator could fake position // all this to let operation know which element sits under cursor...or is there another way to draw stuff that is being dragged? var previousDropTarget = m_CurrentDropTarget; m_CurrentDropTarget = GetDropTargetAt(e.mousePosition, selectedUI.OfType <VisualElement>().ToList()); if (m_CurrentDropTarget != previousDropTarget) { if (previousDropTarget != null) { using (DragLeaveEvent eLeave = DragLeaveEvent.GetPooled(e)) { eLeave.target = previousDropTarget; m_GraphView.SendEvent(eLeave); } } if (m_CurrentDropTarget != null) { using (DragEnterEvent eEnter = DragEnterEvent.GetPooled(e)) { eEnter.target = m_CurrentDropTarget; m_GraphView.SendEvent(eEnter); } } } if (m_CurrentDropTarget != null) { using (DragUpdatedEvent eUpdated = DragUpdatedEvent.GetPooled(e)) { eUpdated.target = m_CurrentDropTarget; m_GraphView.SendEvent(eUpdated); } } m_Dragging = true; e.StopPropagation(); }
public override Rect GetSnappedRect(ref Vector2 snappingOffset, Rect sourceRect, GraphElement selectedElement, float scale, Vector2 mousePanningDelta = default) { if (!IsActive) { throw new InvalidOperationException("SnapStrategy.GetSnappedRect: Snap to borders not active. Call BeginSnap() first."); } if (IsPaused) { // Snapping was paused, we do not return a snapped rect and we clear the snap lines ClearSnapLines(); return(sourceRect); } Rect snappedRect = sourceRect; m_CurrentScale = scale; List <SnapToBordersResult> results = GetClosestSnapElements(sourceRect); m_LineView.lines.Clear(); foreach (SnapToBordersResult result in results) { ApplySnapToBordersResult(ref snappingOffset, sourceRect, ref snappedRect, result); result.IndicatorLine = GetSnapLine(snappedRect, result.SourceReference, result.SnappableRect, result.SnappableReference); m_LineView.lines.Add(result.IndicatorLine); } m_LineView.MarkDirtyRepaint(); m_SnappableRects = GetNotSelectedElementRectsInView(selectedElement); return(snappedRect); }
public abstract Rect GetSnappedRect(ref Vector2 snappingOffset, Rect sourceRect, GraphElement selectedElement, float scale, Vector2 mousePanningDelta = default);
public override Rect GetSnappedRect(ref Vector2 snappingOffset, Rect sourceRect, GraphElement selectedElement, float scale, Vector2 mousePanningDelta = default) { if (!IsActive) { throw new InvalidOperationException("SnapStrategy.GetSnappedRect: Snap to port not active. Call BeginSnap() first."); } if (IsPaused) { // Snapping was paused, we do not return a snapped rect return(sourceRect); } Rect snappedRect = sourceRect; if (selectedElement is Node selectedNode) { m_CurrentScale = scale; SnapToPortResult chosenResult = GetClosestSnapToPortResult(selectedNode, mousePanningDelta); if (chosenResult != null) { var adjustedSourceRect = GetAdjustedSourceRect(chosenResult, sourceRect, mousePanningDelta); snappedRect = adjustedSourceRect; ApplySnapToPortResult(ref snappingOffset, adjustedSourceRect, ref snappedRect, chosenResult); } } return(snappedRect); }