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();
        }
Exemple #3
0
        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));
                }
            }
        }
Exemple #4
0
        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);
        }
Exemple #10
0
        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
            );
        }
Exemple #12
0
        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();
        }