You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

248 lines
7.1 KiB
C#

using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Unity.VisualScripting
{
public abstract class UnitConnectionWidget<TConnection> : GraphElementWidget<FlowCanvas, TConnection>, IUnitConnectionWidget
where TConnection : class, IUnitConnection
{
protected UnitConnectionWidget(FlowCanvas canvas, TConnection connection) : base(canvas, connection) { }
#region Model
protected TConnection connection => element;
protected IUnitConnectionDebugData ConnectionDebugData => GetDebugData<IUnitConnectionDebugData>();
#endregion
#region Lifecycle
public override void BeforeFrame()
{
base.BeforeFrame();
if (showDroplets)
{
GraphGUI.UpdateDroplets(canvas, droplets, ConnectionDebugData.lastInvokeFrame, ref lastInvokeTime, ref dropTime);
}
}
#endregion
#region Positioning
public override IEnumerable<IWidget> positionDependencies
{
get
{
yield return canvas.Widget(connection.source);
yield return canvas.Widget(connection.destination);
}
}
protected override bool snapToGrid => false;
public Rect sourceHandlePosition { get; private set; }
public Rect destinationHandlePosition { get; private set; }
public Vector2 sourceHandleEdgeCenter { get; private set; }
public Vector2 destinationHandleEdgeCenter { get; private set; }
public Vector2 middlePosition;
private Rect _position;
private Rect _clippingPosition;
public override Rect position
{
get { return _position; }
set { }
}
public override Rect clippingPosition => _clippingPosition;
public override void CachePosition()
{
base.CachePosition();
sourceHandlePosition = canvas.Widget<IUnitPortWidget>(connection.source).handlePosition;
destinationHandlePosition = canvas.Widget<IUnitPortWidget>(connection.destination).handlePosition;
sourceHandleEdgeCenter = sourceHandlePosition.GetEdgeCenter(Edge.Right);
destinationHandleEdgeCenter = destinationHandlePosition.GetEdgeCenter(Edge.Left);
middlePosition = (sourceHandlePosition.center + destinationHandlePosition.center) / 2;
_position = new Rect
(
middlePosition.x,
middlePosition.y,
0,
0
);
_clippingPosition = _position.Encompass(sourceHandleEdgeCenter).Encompass(destinationHandleEdgeCenter);
}
#endregion
#region Drawing
protected virtual bool colorIfActive => true;
public abstract Color color { get; }
protected override bool dim
{
get
{
var dim = BoltCore.Configuration.dimInactiveNodes && !connection.destination.unit.Analysis<UnitAnalysis>(context).isEntered;
if (BoltCore.Configuration.dimIncompatibleNodes && canvas.isCreatingConnection)
{
dim = true;
}
return dim;
}
}
public override void DrawBackground()
{
base.DrawBackground();
BeginDim();
DrawConnection();
if (showDroplets)
{
DrawDroplets();
}
EndDim();
}
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);
}
#endregion
#region Selecting
public override bool canSelect => false;
#endregion
#region Dragging
public override bool canDrag => false;
#endregion
#region Deleting
public override bool canDelete => true;
#endregion
#region Droplets
private readonly List<float> droplets = new List<float>();
private float dropTime;
private float lastInvokeTime;
private const float handleAlignmentMargin = 0.1f;
protected virtual bool showDroplets => true;
protected abstract Vector2 GetDropletSize();
protected abstract void DrawDroplet(Rect position);
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));
}
}
}
#endregion
}
}