private void DrawDroplets() { foreach (var droplet in droplets) { Vector2 position; if (droplet < 0.5f) { var t = droplet / 0.5f; position = GraphGUI.GetPointOnConnection(t, sourceEdgeCenter, entryEdgeCenter, sourceEdge, entryEdge, relativeBend, minBend); } else { var t = (droplet - 0.5f) / 0.5f; position = GraphGUI.GetPointOnConnection(t, exitEdgeCenter, destinationEdgeCenter, exitEdge, destinationEdge, relativeBend, minBend); } var size = GetDropletSize(); using (LudiqGUI.color.Override(Color.white)) { DrawDroplet(new Rect(position.x - size.x / 2, position.y - size.y / 2, size.x, size.y)); } } }
public void Drag(Vector2 delta, Vector2 constraint) { dragPosition.position += delta; var lockedPosition = dragPosition; if (constraint.x == 0) { lockedPosition.x = dragLockOrigin.x; } if (constraint.y == 0) { lockedPosition.y = dragLockOrigin.y; } if (snapToGrid) { position = GraphGUI.SnapToGrid(lockedPosition, canResizeHorizontal && canResizeVertical); } else { position = lockedPosition.PixelPerfect(); } Reposition(); }
protected virtual void DrawDroplets() { foreach (var droplet in droplets) { Vector2 position; if (droplet < handleAlignmentMargin) { var t = droplet / handleAlignmentMargin; position = Vector2.Lerp(sourceHandlePosition.center, sourceHandleEdgeCenter, t); } else if (droplet > 1 - handleAlignmentMargin) { var t = (droplet - (1 - handleAlignmentMargin)) / handleAlignmentMargin; position = Vector2.Lerp(destinationHandleEdgeCenter, destinationHandlePosition.center, t); } else { var t = (droplet - handleAlignmentMargin) / (1 - 2 * handleAlignmentMargin); position = GraphGUI.GetPointOnConnection(t, sourceHandleEdgeCenter, destinationHandleEdgeCenter, Edge.Right, Edge.Left, UnitConnectionStyles.relativeBend, UnitConnectionStyles.minBend); } var size = GetDropletSize(); using (LudiqGUI.color.Override(GUI.color * color)) { DrawDroplet(new Rect(position.x - size.x / 2, position.y - size.y / 2, size.x, size.y)); } } }
public override void BeforeFrame() { base.BeforeFrame(); if (showDroplets) { GraphGUI.UpdateDroplets(canvas, droplets, ConnectionDebugData.lastInvokeFrame, ref lastInvokeTime, ref dropTime); } }
public override void DrawForeground() { base.DrawForeground(); if (e.IsRepaint) { GraphGUI.Node(edgePosition.PixelPerfect(), shape, color, isSelected); } }
public override void DrawDragAndDropPreview() { if (DragAndDropUtility.Is <ScriptGraphAsset>()) { GraphGUI.DrawDragAndDropPreviewLabel(DragAndDropUtility.offsetedPosition, DragAndDropUtility.Get <ScriptGraphAsset>().name, typeof(ScriptGraphAsset).Icon()); } else if (DragAndDropUtility.Is <StateGraphAsset>()) { GraphGUI.DrawDragAndDropPreviewLabel(DragAndDropUtility.offsetedPosition, DragAndDropUtility.Get <StateGraphAsset>().name, typeof(StateGraphAsset).Icon()); } }
private void DrawConnection() { GraphGUI.DrawConnectionArrow(Color.white, sourceEdgeCenter, entryEdgeCenter, sourceEdge, entryEdge, relativeBend, minBend); if (BoltState.Configuration.transitionsEndArrow) { GraphGUI.DrawConnectionArrow(Color.white, exitEdgeCenter, destinationEdgeCenter, exitEdge, destinationEdge, relativeBend, minBend); } else { GraphGUI.DrawConnection(Color.white, exitEdgeCenter, destinationEdgeCenter, exitEdge, destinationEdge, null, Vector2.zero, relativeBend, minBend); } }
public override void BeforeFrame() { base.BeforeFrame(); if (showDroplets) { GraphGUI.UpdateDroplets(canvas, droplets, transitionDebugData.lastBranchFrame, ref lastBranchTime, ref dropTime); } if (currentInnerWidth != targetInnerWidth) { Reposition(); } }
public void CompleteTransitionToNewState() { var startRect = this.Widget(transitionSource).position; var end = mousePosition; GraphGUI.GetConnectionEdge ( startRect.center, end, out var startEdge, out var endEdge ); var destination = FlowState.WithEnterUpdateExit(); graph.states.Add(destination); Vector2 offset; var size = this.Widget(destination).position.size; switch (endEdge) { case Edge.Left: offset = new Vector2(0, -size.y / 2); break; case Edge.Right: offset = new Vector2(-size.x, -size.y / 2); break; case Edge.Top: offset = new Vector2(-size.x / 2, 0); break; case Edge.Bottom: offset = new Vector2(-size.x / 2, -size.y); break; default: throw new UnexpectedEnumValueException <Edge>(endEdge); } destination.position = mousePosition + offset; destination.position = destination.position.PixelPerfect(); EndTransition(destination); }
public override void DrawDragAndDropPreview() { if (DragAndDropUtility.Is <ScriptGraphAsset>()) { GraphGUI.DrawDragAndDropPreviewLabel(DragAndDropUtility.offsetedPosition, DragAndDropUtility.Get <ScriptGraphAsset>().name, typeof(ScriptGraphAsset).Icon()); } else if (DragAndDropUtility.Is <GameObject>()) { var gameObject = DragAndDropUtility.Get <GameObject>(); GraphGUI.DrawDragAndDropPreviewLabel(DragAndDropUtility.offsetedPosition, gameObject.name + "...", gameObject.Icon()); } else if (DragAndDropUtility.Is <UnityObject>()) { var obj = DragAndDropUtility.Get <UnityObject>(); var type = obj.GetType(); GraphGUI.DrawDragAndDropPreviewLabel(DragAndDropUtility.offsetedPosition, type.HumanName() + "...", type.Icon()); } else if (EditorVariablesUtility.isDraggingVariable) { var kind = EditorVariablesUtility.kind; var name = EditorVariablesUtility.declaration.name; string label; if (e.alt) { label = $"Set {name}"; } else if (e.shift) { label = $"Check if {name} is defined"; } else { label = $"Get {name}"; } GraphGUI.DrawDragAndDropPreviewLabel(DragAndDropUtility.offsetedPosition, label, BoltCore.Icons.VariableKind(kind)); } }
private void DrawConnectionSource() { var start = handlePosition.GetEdgeCenter(edge); if (window.IsFocused()) { canvas.connectionEnd = mousePosition; } GraphGUI.DrawConnection ( color, start, canvas.connectionEnd, edge, null, handleTextureConnected, Styles.handleSize, UnitConnectionStyles.relativeBend, UnitConnectionStyles.minBend ); }
protected virtual void DrawConnection() { var color = this.color; var sourceWidget = canvas.Widget <IUnitPortWidget>(connection.source); var destinationWidget = canvas.Widget <IUnitPortWidget>(connection.destination); var highlight = !canvas.isCreatingConnection && (sourceWidget.isMouseOver || destinationWidget.isMouseOver); var willDisconnect = sourceWidget.willDisconnect || destinationWidget.willDisconnect; if (willDisconnect) { color = UnitConnectionStyles.disconnectColor; } else if (highlight) { color = UnitConnectionStyles.highlightColor; } else if (colorIfActive) { if (EditorApplication.isPaused) { if (EditorTimeBinding.frame == ConnectionDebugData.lastInvokeFrame) { color = UnitConnectionStyles.activeColor; } } else { color = Color.Lerp(UnitConnectionStyles.activeColor, color, (EditorTimeBinding.time - ConnectionDebugData.lastInvokeTime) / UnitWidget <IUnit> .Styles.invokeFadeDuration); } } var thickness = 3; GraphGUI.DrawConnection(color, sourceHandleEdgeCenter, destinationHandleEdgeCenter, Edge.Right, Edge.Left, null, Vector2.zero, UnitConnectionStyles.relativeBend, UnitConnectionStyles.minBend, thickness); }
protected override void DrawBackground() { base.DrawBackground(); if (isCreatingTransition) { var startRect = this.Widget(transitionSource).position; var end = mousePosition; Edge startEdge, endEdge; GraphGUI.GetConnectionEdge ( startRect.center, end, out startEdge, out endEdge ); var start = startRect.GetEdgeCenter(startEdge); GraphGUI.DrawConnectionArrow(Color.white, start, end, startEdge, endEdge); } }
protected Rect InnerToEdgePosition(Rect position) { return(GraphGUI.GetNodeInnerToEdgePosition(position, shape)); }
protected Rect EdgeToInnerPosition(Rect position) { return(GraphGUI.GetNodeEdgeToInnerPosition(position, shape)); }
private void HandleResizing() { if (e.IsMouseDrag(MouseButton.Left) && !isResizing && canStartResize) { if (resizeLeftArea.Contains(mousePosition)) { isResizingXMin = true; xMinResizeOffset = mousePosition.x - position.xMin; } if (resizeRightArea.Contains(mousePosition)) { isResizingXMax = true; xMaxResizeOffset = mousePosition.x - position.xMax; } if (resizeTopArea.Contains(mousePosition)) { isResizingYMin = true; yMinResizeOffset = mousePosition.y - position.yMin; } if (resizeBottomArea.Contains(mousePosition)) { isResizingYMax = true; yMaxResizeOffset = mousePosition.y - position.yMax; } if (resizeTopLeftArea.Contains(mousePosition)) { isResizingXMin = true; isResizingYMin = true; xMinResizeOffset = mousePosition.x - position.xMin; yMinResizeOffset = mousePosition.y - position.yMin; } if (resizeTopRightArea.Contains(mousePosition)) { isResizingXMax = true; isResizingYMin = true; xMaxResizeOffset = mousePosition.x - position.xMax; yMinResizeOffset = mousePosition.y - position.yMin; } if (resizeBottomLeftArea.Contains(mousePosition)) { isResizingXMin = true; isResizingYMax = true; xMinResizeOffset = mousePosition.x - position.xMin; yMaxResizeOffset = mousePosition.y - position.yMax; } if (resizeBottomRightArea.Contains(mousePosition)) { isResizingXMax = true; isResizingYMax = true; xMaxResizeOffset = mousePosition.x - position.xMax; yMaxResizeOffset = mousePosition.y - position.yMax; } e.Use(); } else if (e.IsMouseDrag(MouseButton.Left) && isResizing) { var resizedPosition = position; if (isResizingXMin) { resizedPosition.xMin = Mathf.Min(position.xMax - minResizeSize.x, mousePosition.x - xMinResizeOffset); if (snapToGrid) { resizedPosition.xMin = GraphGUI.SnapToGrid(resizedPosition.xMin); } } if (isResizingXMax) { resizedPosition.xMax = Mathf.Max(position.xMin + minResizeSize.x, mousePosition.x - xMaxResizeOffset); if (snapToGrid) { resizedPosition.xMax = GraphGUI.SnapToGrid(resizedPosition.xMax); } } if (isResizingYMin) { resizedPosition.yMin = Mathf.Min(position.yMax - minResizeSize.y, mousePosition.y - yMinResizeOffset); if (snapToGrid) { resizedPosition.yMin = GraphGUI.SnapToGrid(resizedPosition.yMin); } } if (isResizingYMax) { resizedPosition.yMax = Mathf.Max(position.yMin + minResizeSize.y, mousePosition.y - yMaxResizeOffset); if (snapToGrid) { resizedPosition.yMax = GraphGUI.SnapToGrid(resizedPosition.yMax); } } resizedPosition.width = Mathf.Clamp(resizedPosition.width, minResizeSize.x, maxResizeSize.x); resizedPosition.height = Mathf.Clamp(resizedPosition.height, minResizeSize.y, maxResizeSize.y); UndoUtility.RecordEditedObject("Resize Graph Element"); position = resizedPosition; Reposition(); e.Use(); } else if (e.IsMouseUp(MouseButton.Left) && isResizing) { isResizingXMin = false; isResizingXMax = false; isResizingYMin = false; isResizingYMax = false; e.Use(); } }
public override void CachePosition() { var innerWidth = innerPosition.width; var innerHeight = innerPosition.height; var edgeWidth = edgePosition.width; var edgeHeight = edgePosition.height; var labelWidth = Styles.label.CalcSize(label).x; var labelHeight = EditorGUIUtility.singleLineHeight; sourcePosition = canvas.Widget(transition.source).position; destinationPosition = canvas.Widget(transition.destination).position; Vector2 sourceClosestPoint; Vector2 destinationClosestPoint; LudiqGUIUtility.ClosestPoints(sourcePosition, destinationPosition, out sourceClosestPoint, out destinationClosestPoint); if (transition.destination != transition.source) { GraphGUI.GetConnectionEdge ( sourceClosestPoint, destinationClosestPoint, out sourceEdge, out destinationEdge ); } else { sourceEdge = Edge.Right; destinationEdge = Edge.Left; } sourceEdgeCenter = sourcePosition.GetEdgeCenter(sourceEdge); destinationEdgeCenter = destinationPosition.GetEdgeCenter(destinationEdge); siblingStateTransitions.Clear(); var siblingIndex = 0; // Assign one common axis for transition for all siblings, // regardless of their inversion. The axis is arbitrarily // chosen as the axis for the first transition. var assignedTransitionAxis = false; var transitionAxis = Vector2.zero; foreach (var graphTransition in canvas.graph.transitions) { var current = transition == graphTransition; var analog = transition.source == graphTransition.source && transition.destination == graphTransition.destination; var inverted = transition.source == graphTransition.destination && transition.destination == graphTransition.source; if (current) { siblingIndex = siblingStateTransitions.Count; } if (current || analog || inverted) { if (!assignedTransitionAxis) { var siblingStateTransitionDrawer = canvas.Widget <IStateTransitionWidget>(graphTransition); transitionAxis = siblingStateTransitionDrawer.sourceEdge.Normal(); assignedTransitionAxis = true; } siblingStateTransitions.Add(graphTransition); } } // Fix the edge case where the source and destination perfectly overlap if (transitionAxis == Vector2.zero) { transitionAxis = Vector2.right; } // Calculate the spread axis and origin for the set of siblings var spreadAxis = transitionAxis.Perpendicular1().Abs(); var spreadOrigin = (sourceEdgeCenter + destinationEdgeCenter) / 2; if (transition.source == transition.destination) { spreadAxis = Vector2.up; spreadOrigin = sourcePosition.GetEdgeCenter(Edge.Bottom) - Vector2.down * 10; } if (BoltCore.Configuration.developerMode && BoltCore.Configuration.debug) { Handles.BeginGUI(); Handles.color = Color.yellow; Handles.DrawLine(spreadOrigin + spreadAxis * -1000, spreadOrigin + spreadAxis * 1000); Handles.EndGUI(); } // Calculate the offset of the current sibling by iterating over its predecessors var spreadOffset = 0f; var previousSpreadSize = 0f; for (var i = 0; i <= siblingIndex; i++) { var siblingSize = canvas.Widget <IStateTransitionWidget>(siblingStateTransitions[i]).outerPosition.size; var siblingSizeProjection = GraphGUI.SizeProjection(siblingSize, spreadOrigin, spreadAxis); spreadOffset += previousSpreadSize / 2 + siblingSizeProjection / 2; previousSpreadSize = siblingSizeProjection; } if (transition.source != transition.destination) { // Calculate the total spread size to center the sibling set var totalSpreadSize = 0f; for (var i = 0; i < siblingStateTransitions.Count; i++) { var siblingSize = canvas.Widget <IStateTransitionWidget>(siblingStateTransitions[i]).outerPosition.size; var siblingSizeProjection = GraphGUI.SizeProjection(siblingSize, spreadOrigin, spreadAxis); totalSpreadSize += siblingSizeProjection; } spreadOffset -= totalSpreadSize / 2; } // Finally, calculate the positions middle = spreadOrigin + spreadOffset * spreadAxis; var edgeX = middle.x - edgeWidth / 2; var edgeY = middle.y - edgeHeight / 2; _position = new Rect ( edgeX, edgeY, edgeWidth, edgeHeight ).PixelPerfect(); var innerX = innerPosition.x; var innerY = innerPosition.y; _clippingPosition = _position.Encompass(sourceEdgeCenter).Encompass(destinationEdgeCenter); if (transition.source != transition.destination) { entryEdge = destinationEdge; exitEdge = sourceEdge; } else { entryEdge = sourceEdge; exitEdge = destinationEdge; } entryEdgeCenter = edgePosition.GetEdgeCenter(entryEdge); exitEdgeCenter = edgePosition.GetEdgeCenter(exitEdge); var x = innerX; iconPosition = new Rect ( x, innerY, Styles.eventIcon.fixedWidth, Styles.eventIcon.fixedHeight ).PixelPerfect(); x += iconPosition.width; var clipWidth = innerWidth - (x - innerX); clipPosition = new Rect ( x, edgeY, clipWidth, edgeHeight ).PixelPerfect(); labelInnerPosition = new Rect ( Styles.spaceAroundIcon, innerY - edgeY, labelWidth, labelHeight ).PixelPerfect(); }
public void DrawDragAndDropPreview() { GraphGUI.DrawDragAndDropPreviewLabel(new Vector2(edgePosition.x, outerPosition.yMax), "Replace with: " + DragAndDropUtility.Get <StateGraphAsset>().name, typeof(StateGraphAsset).Icon()); }
public static void PasteOutside(bool reposition, Vector2?position = null) { if (!canPasteOutside) { throw new InvalidOperationException(); } UndoUtility.RecordEditedObject("Paste Graph Elements"); var pastedElements = GetPasteGroup(); // Assign new GUIDs foreach (var pastedElement in pastedElements) { pastedElement.guid = Guid.NewGuid(); } // Add elements to graph and selection selection.Clear(); foreach (var pastedElement in pastedElements) { if (!pastedElement.HandleDependencies()) { continue; } graph.elements.Add(pastedElement); selection.Add(pastedElement); } canvas.Cache(); foreach (var pastedElement in pastedElements) { var pastedWidget = canvas.Widget(pastedElement); pastedWidget.BringToFront(); } var pastedWidgets = pastedElements.Select(e => canvas.Widget(e)).ToList(); // Recenter elements in graph view if (reposition) { var area = GraphGUI.CalculateArea(pastedWidgets.Where(widget => widget.canDrag)); Vector2 delta; if (position.HasValue) { delta = position.Value - area.position; } else { delta = graph.pan - area.center; } foreach (var pastedWidget in pastedWidgets) { if (pastedWidget.canDrag) { pastedWidget.position = new Rect(pastedWidget.position.position + delta, pastedWidget.position.size).PixelPerfect(); pastedWidget.Reposition(); pastedWidget.CachePositionFirstPass(); pastedWidget.CachePosition(); } } } // Space out overlapping elements foreach (var pastedWidget in pastedWidgets) { if (pastedWidget.canDrag) { var distanciation = 20; var timeout = 100; var timeoutIndex = 0; while (GraphGUI.PositionOverlaps(canvas, pastedWidget, 5)) { // Space the widget out pastedWidget.position = new Rect(pastedWidget.position.position + new Vector2(distanciation, distanciation), pastedWidget.position.size).PixelPerfect(); // Calculate the resulting position immediately pastedWidget.CachePositionFirstPass(); pastedWidget.CachePosition(); // Mark it as invalid still so dependencies like ports will be recached pastedWidget.Reposition(); // Failsafe to keep the editor from freezing if (++timeoutIndex > timeout) { Debug.LogWarning($"Failed to space out pasted element: {pastedWidget.element}"); break; } } } } canvas.Cache(); GUI.changed = true; e?.TryUse(); }