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.IsSelectable()) { Vector2 localMousePosition = currentTarget.ChangeCoordinatesTo(descendant, evt.localMousePosition); if (selectableDescendant.HitTest(localMousePosition)) { return(true); } } descendant = descendant.parent; } return(false); }
private void OnChildAdded(GraphElement element) { element.AddToClassList("stack-child-element"); element.ResetPositionProperties(); element.RegisterCallback <DetachFromPanelEvent>(OnChildDetachedFromPanel); UpdatePlaceholderVisibility(); }
protected void OnMouseMove(MouseMoveEvent e) { GraphElement ce = e.target as GraphElement; if (ce != null && !ce.IsMovable()) { return; } if (m_Active) { Vector2 diff = e.localMousePosition - m_Start; if (ce != null) { var targetScale = ce.transform.scale; diff.x *= targetScale.x; diff.y *= targetScale.y; } Rect rect = CalculatePosition(target.layout.x + diff.x, target.layout.y + diff.y, target.layout.width, target.layout.height); if (target.isLayoutManual) { target.layout = rect; } else if (target.resolvedStyle.position == Position.Absolute) { target.style.left = rect.x; target.style.top = rect.y; } e.StopPropagation(); } }
protected void OnMouseUp(MouseUpEvent e) { GraphElement ce = e.target as GraphElement; if (ce != null && !ce.IsMovable()) { return; } if (m_Active) { if (CanStopManipulation(e)) { var graphElement = target as GraphElement; if (graphElement != null) { graphElement.UpdatePresenterPosition(); } m_Active = false; target.ReleaseMouse(); e.StopPropagation(); } } }
private void AddElementInternal(GraphElement element) { if (element == null) { throw new ArgumentException("Cannot add null element"); } if (containedElements.Contains(element)) { throw new ArgumentException("The specified element is already contained in this scope."); } string reasonWhyNotAccepted = "Cannot add the specified element to this scope."; if (!AcceptsElement(element, ref reasonWhyNotAccepted)) { throw new ArgumentException(reasonWhyNotAccepted); } // Removes the element from its current scope Scope currentScope = element.GetContainingScope(); if (currentScope != null) { currentScope.RemoveElement(element); } m_ContainedElements.Add(element); element.SetContainingScope(this); // To update the scope geometry whenever the added element's geometry changes element.RegisterCallback <GeometryChangedEvent>(OnSubElementGeometryChanged); ScheduleUpdateGeometryFromContent(); }
private bool AcceptsElementInternal(GraphElement element, ref int proposedIndex, int maxIndex) { return(element != null && !(element is Scope) && !(element is StackNode) && !(element is TokenNode) && (element.GetContainingScope() as Group) == null && AcceptsElement(element, ref proposedIndex, maxIndex)); }
private static VisualElement DefaultDropPreviewTemplate(GraphElement source) { VisualElement preview = new VisualElement(); preview.AddToClassList("default"); return(preview); }
private VisualElement CreateDropPreview(GraphElement element) { VisualElement preview = dropPreviewTemplate(element); preview.Add(new Label(element.title)); preview.AddToClassList(k_PreviewClass); return(preview); }
public static Scope GetContainingScope(this GraphElement element) { if (element == null) { return(null); } return(element.GetProperty(containingScopePropertyKey) as Scope); }
private bool AcceptsElementInternal(GraphElement element, ref int proposedIndex, int maxIndex) { // TODO: we probably need a "Stackable" capability return(element != null && !(element is Scope) && !(element is StackNode) && !(element is TokenNode) && !(element is Placemat) && (element.GetContainingScope() as Group) == null && AcceptsElement(element, ref proposedIndex, maxIndex)); }
internal static void SetContainingScope(this GraphElement element, Scope scope) { if (element == null) { throw new ArgumentNullException(nameof(element)); } element.SetProperty(containingScopePropertyKey, scope); }
Rect CalculateElementRect(GraphElement elem) { Rect rect = elem.ChangeCoordinatesTo(graphView.contentViewContainer, elem.rect); rect.x = m_ContentRect.x + ((rect.x - m_ContentRectLocal.x) * m_ContentRect.width / m_ContentRectLocal.width); rect.y = m_ContentRect.y + ((rect.y - m_ContentRectLocal.y) * m_ContentRect.height / m_ContentRectLocal.height); rect.width *= m_ContentRect.width / m_ContentRectLocal.width; rect.height *= m_ContentRect.height / m_ContentRectLocal.height; // Clip using a minimal 2 pixel wide frame around edges // (except yMin since we already have the titleBar offset which is enough for clipping) var xMin = 2; var yMin = windowed ? 2 : 0; var xMax = layout.width - 2; var yMax = layout.height - 2; if (rect.x < xMin) { if (rect.x < xMin - rect.width) { return(new Rect(0, 0, 0, 0)); } rect.width -= xMin - rect.x; rect.x = xMin; } if (rect.x + rect.width >= xMax) { if (rect.x >= xMax) { return(new Rect(0, 0, 0, 0)); } rect.width -= rect.x + rect.width - xMax; } if (rect.y < yMin + titleBarOffset) { if (rect.y < yMin + titleBarOffset - rect.height) { return(new Rect(0, 0, 0, 0)); } rect.height -= yMin + titleBarOffset - rect.y; rect.y = yMin + titleBarOffset; } if (rect.y + rect.height >= yMax) { if (rect.y >= yMax) { return(new Rect(0, 0, 0, 0)); } rect.height -= rect.y + rect.height - yMax; } return(rect); }
public virtual bool AcceptsElement(GraphElement element, ref string reasonWhyNotAccepted) { if (element.GetType() == typeof(Scope)) { reasonWhyNotAccepted = "Nested scope is not supported yet."; return(false); } return(true); }
private void OnChildDetachedFromPanel(DetachFromPanelEvent evt) { if (panel == null) { return; } GraphElement element = evt.target as GraphElement; OnChildRemoved(element); }
private void OnChildAdded(GraphElement element) { element.AddToClassList("stack-child-element"); // these capabilities should be set correctly on contruction of stackable nodes (in client/dependent code), // -- Since the module didn't have a way of identifying stackable nodes previously, we can provide some identity here. // TODO: Remove this once deps have an opportunity to use the flags. element.capabilities &= ~(Capabilities.Snappable | Capabilities.Stackable | Capabilities.Groupable); element.ResetPositionProperties(); element.RegisterCallback <DetachFromPanelEvent>(OnChildDetachedFromPanel); UpdatePlaceholderVisibility(); }
private void OnChildRemoved(GraphElement element) { element.RemoveFromClassList("stack-child-element"); element.UnregisterCallback <DetachFromPanelEvent>(OnChildDetachedFromPanel); // Disable the animation temporarily if (m_InstantAdd == false) { m_InstantAdd = true; schedule.Execute(() => m_InstantAdd = false); } UpdatePlaceholderVisibility(); }
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) * panSpeed.x / scale.x * element.transform.scale.x; newPos.y = originalPos.y - (m_MouseDiff.y - m_ItemPanDiff.y) * panSpeed.y / scale.y * element.transform.scale.y; element.SetPosition(m_GraphView.contentViewContainer.ChangeCoordinatesTo(element.hierarchy.parent, newPos)); }
public virtual void OnStartDragging(GraphElement ge) { var node = ge as Node; if (node != null) { ge.RemoveFromHierarchy(); graphView.AddElement(ge); // Reselect it because RemoveFromHierarchy unselected it ge.Select(graphView, true); } }
void SnapOrMoveElement(KeyValuePair <GraphElement, OriginalPos> v, Rect selectedElementGeom) { GraphElement ce = v.Key; if (EditorPrefs.GetBool("GraphSnapping")) { Vector2 geomDiff = selectedElementGeom.position - m_OriginalPos[selectedElement].pos.position; Rect ceLayout = ce.GetPosition(); ce.SetPosition(new Rect(v.Value.pos.x + geomDiff.x, v.Value.pos.y + geomDiff.y, ceLayout.width, ceLayout.height)); } else { MoveElement(ce, v.Value.pos); } }
public void InsertElement(int index, GraphElement element) { if (!AcceptsElementInternal(element, ref index, childCount)) { return; } Insert(index, element); OnChildAdded(element); if (graphView != null) { graphView.RestorePersitentSelectionForElement(element); } }
public override bool AcceptsElement(GraphElement element, ref string reasonWhyNotAccepted) { if (element is Group) { reasonWhyNotAccepted = "Nested group is not supported yet."; return(false); } else if (element is Scope) { reasonWhyNotAccepted = "Nested scope is not supported yet."; return(false); } return(true); }
private void RemoveElementInternal(GraphElement element) { if (element == null) { throw new ArgumentException("Cannot remove null element from this scope"); } if (!m_ContainedElements.Contains(element)) { throw new ArgumentException("This element is not contained in this scope"); } element.UnregisterCallback <GeometryChangedEvent>(OnSubElementGeometryChanged); m_ContainedElements.Remove(element); element.SetContainingScope(null); ScheduleUpdateGeometryFromContent(); }
protected void OnMouseDown(MouseDownEvent e) { if (m_Active) { e.StopImmediatePropagation(); return; } GraphElement ce = e.target as GraphElement; if (ce != null && !ce.IsMovable()) { return; } if (CanStartManipulation(e)) { m_Start = e.localMousePosition; m_Active = true; target.CaptureMouse(); e.StopPropagation(); } }
protected new 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; var groupElementsDraggedOut = e.shiftKey ? new Dictionary <Group, List <GraphElement> >() : null; // Handle the selected element Rect selectedElementGeom = GetSelectedElementGeom(); m_ShiftClicked = e.shiftKey; if (snapEnabled && !m_ShiftClicked) { ComputeSnappedRect(ref selectedElementGeom, m_XScale); } if (snapEnabled && m_ShiftClicked) { m_Snapper.ClearSnapLines(); } 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) { // TODO Would probably be a good idea to batch stack items as we do for group ones. var stackParent = ce.GetFirstAncestorOfType <StackNode>(); if (stackParent != null) { stackParent.OnStartDragging(ce); } if (groupElementsDraggedOut != null) { var groupParent = ce.GetContainingScope() as Group; if (groupParent != null) { if (!groupElementsDraggedOut.ContainsKey(groupParent)) { groupElementsDraggedOut[groupParent] = new List <GraphElement>(); } groupElementsDraggedOut[groupParent].Add(ce); } } v.Value.dragStarted = true; } SnapOrMoveElement(v, selectedElementGeom); } // Needed to ensure nodes can be dragged out of multiple groups all at once. if (groupElementsDraggedOut != null) { foreach (KeyValuePair <Group, List <GraphElement> > kvp in groupElementsDraggedOut) { kvp.Key.OnStartDragging(e, kvp.Value); } } List <ISelectable> selection = m_GraphView.selection; // 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? IDropTarget dropTarget = GetDropTargetAt(e.mousePosition, selection.OfType <VisualElement>()); if (m_PrevDropTarget != dropTarget) { if (m_PrevDropTarget != null) { using (DragLeaveEvent eexit = DragLeaveEvent.GetPooled(e)) { SendDragAndDropEvent(eexit, selection, m_PrevDropTarget, m_GraphView); } } using (DragEnterEvent eenter = DragEnterEvent.GetPooled(e)) { SendDragAndDropEvent(eenter, selection, dropTarget, m_GraphView); } } using (DragUpdatedEvent eupdated = DragUpdatedEvent.GetPooled(e)) { SendDragAndDropEvent(eupdated, selection, dropTarget, m_GraphView); } m_PrevDropTarget = dropTarget; m_Dragging = true; e.StopPropagation(); }
protected new void OnMouseDown(MouseDownEvent e) { if (m_Active) { e.StopImmediatePropagation(); return; } if (CanStartManipulation(e)) { m_GraphView = target as GraphView; if (m_GraphView == null) { return; } selectedElement = null; // avoid starting a manipulation on a non movable object clickedElement = e.target as GraphElement; if (clickedElement == null) { var ve = e.target as VisualElement; clickedElement = ve.GetFirstAncestorOfType <GraphElement>(); if (clickedElement == null) { return; } } // Only start manipulating if the clicked element is movable, selected and that the mouse is in its clickable region (it must be deselected otherwise). if (!clickedElement.IsMovable() || !clickedElement.HitTest(clickedElement.WorldToLocal(e.mousePosition))) { return; } // If we hit this, this likely because the element has just been unselected // It is important for this manipulator to receive the event so the previous one did not stop it // but we shouldn't let it propagate to other manipulators to avoid a re-selection if (!m_GraphView.selection.Contains(clickedElement)) { e.StopImmediatePropagation(); return; } selectedElement = clickedElement; m_OriginalPos = new Dictionary <GraphElement, OriginalPos>(); HashSet <GraphElement> elementsToMove = new HashSet <GraphElement>(m_GraphView.selection.OfType <GraphElement>()); var selectedPlacemats = new HashSet <Placemat>(elementsToMove.OfType <Placemat>()); foreach (var placemat in selectedPlacemats) { placemat.GetElementsToMove(e.shiftKey, elementsToMove); } foreach (GraphElement ce in elementsToMove) { if (ce == null || !ce.IsMovable()) { continue; } StackNode stackNode = null; if (ce.parent is StackNode) { stackNode = ce.parent as StackNode; if (stackNode.IsSelected(m_GraphView)) { continue; } } Rect geometry = ce.GetPosition(); Rect geometryInContentViewSpace = ce.hierarchy.parent.ChangeCoordinatesTo(m_GraphView.contentViewContainer, geometry); m_OriginalPos[ce] = new OriginalPos { pos = geometryInContentViewSpace, scope = ce.GetContainingScope(), stack = stackNode, stackIndex = stackNode != null?stackNode.IndexOf(ce) : -1 }; } m_originalMouse = e.mousePosition; m_ItemPanDiff = Vector3.zero; if (m_PanSchedule == null) { m_PanSchedule = m_GraphView.schedule.Execute(Pan).Every(k_PanInterval).StartingIn(k_PanInterval); m_PanSchedule.Pause(); } // Checking if the Graph Element we are moving has the snappable Capability if ((selectedElement.capabilities & Capabilities.Snappable) == 0) { snapEnabled = false; } else { snapEnabled = EditorPrefs.GetBool("GraphSnapping", true); } if (snapEnabled) { m_Snapper.BeginSnap(m_GraphView); } m_Active = true; target.CaptureMouse(); // We want to receive events even when mouse is not over ourself. e.StopImmediatePropagation(); } }
Rect CalculateElementRect(GraphElement elem) { // TODO: Should Edges be displayed at all? // TODO: Maybe edges need their own capabilities flag. if (elem is Edge || elem is Port) { return(new Rect(0, 0, 0, 0)); } Rect rect = elem.ChangeCoordinatesTo(graphView.contentViewContainer, elem.rect); rect.x = m_ContentRect.x + ((rect.x - m_ContentRectLocal.x) * m_ContentRect.width / m_ContentRectLocal.width); rect.y = m_ContentRect.y + ((rect.y - m_ContentRectLocal.y) * m_ContentRect.height / m_ContentRectLocal.height); rect.width *= m_ContentRect.width / m_ContentRectLocal.width; rect.height *= m_ContentRect.height / m_ContentRectLocal.height; // Clip using a minimal 2 pixel wide frame around edges // (except yMin since we already have the titleBar offset which is enough for clipping) var xMin = 2; var yMin = 0; var xMax = layout.width - 2; var yMax = layout.height - 2; if (rect.x < xMin) { if (rect.x < xMin - rect.width) { return(new Rect(0, 0, 0, 0)); } rect.width -= xMin - rect.x; rect.x = xMin; } if (rect.x + rect.width >= xMax) { if (rect.x >= xMax) { return(new Rect(0, 0, 0, 0)); } rect.width -= rect.x + rect.width - xMax; } if (rect.y < yMin + titleBarOffset) { if (rect.y < yMin + titleBarOffset - rect.height) { return(new Rect(0, 0, 0, 0)); } rect.height -= yMin + titleBarOffset - rect.y; rect.y = yMin + titleBarOffset; } if (rect.y + rect.height >= yMax) { if (rect.y >= yMax) { return(new Rect(0, 0, 0, 0)); } rect.height -= rect.y + rect.height - yMax; } return(rect); }
public void RemoveElement(GraphElement element) { RemoveElementInternal(element); OnElementsRemoved(new[] { element }); }
public void RemoveElement(GraphElement element) { Remove(element); }
public void AddElement(GraphElement element) { InsertElement(childCount, element); }
protected virtual bool AcceptsElement(GraphElement element, ref int proposedIndex, int maxIndex) { return(true); }