A game about forced loneliness, made by TACStudios
1using System.Collections.Generic;
2using UnityEditor;
3using UnityEngine;
4
5namespace Unity.VisualScripting
6{
7 public abstract class UnitConnectionWidget<TConnection> : GraphElementWidget<FlowCanvas, TConnection>, IUnitConnectionWidget
8 where TConnection : class, IUnitConnection
9 {
10 protected UnitConnectionWidget(FlowCanvas canvas, TConnection connection) : base(canvas, connection) { }
11
12
13 #region Model
14
15 protected TConnection connection => element;
16
17 protected IUnitConnectionDebugData ConnectionDebugData => GetDebugData<IUnitConnectionDebugData>();
18
19 #endregion
20
21
22 #region Lifecycle
23
24 public override void BeforeFrame()
25 {
26 base.BeforeFrame();
27
28 if (showDroplets)
29 {
30 GraphGUI.UpdateDroplets(canvas, droplets, ConnectionDebugData.lastInvokeFrame, ref lastInvokeTime, ref dropTime);
31 }
32 }
33
34 #endregion
35
36
37 #region Positioning
38
39 public override IEnumerable<IWidget> positionDependencies
40 {
41 get
42 {
43 yield return canvas.Widget(connection.source);
44 yield return canvas.Widget(connection.destination);
45 }
46 }
47
48 protected override bool snapToGrid => false;
49
50 public Rect sourceHandlePosition { get; private set; }
51
52 public Rect destinationHandlePosition { get; private set; }
53
54 public Vector2 sourceHandleEdgeCenter { get; private set; }
55
56 public Vector2 destinationHandleEdgeCenter { get; private set; }
57
58 public Vector2 middlePosition;
59
60 private Rect _position;
61
62 private Rect _clippingPosition;
63
64 public override Rect position
65 {
66 get { return _position; }
67 set { }
68 }
69
70 public override Rect clippingPosition => _clippingPosition;
71
72 public override void CachePosition()
73 {
74 base.CachePosition();
75
76 sourceHandlePosition = canvas.Widget<IUnitPortWidget>(connection.source).handlePosition;
77 destinationHandlePosition = canvas.Widget<IUnitPortWidget>(connection.destination).handlePosition;
78
79 sourceHandleEdgeCenter = sourceHandlePosition.GetEdgeCenter(Edge.Right);
80 destinationHandleEdgeCenter = destinationHandlePosition.GetEdgeCenter(Edge.Left);
81
82 middlePosition = (sourceHandlePosition.center + destinationHandlePosition.center) / 2;
83
84 _position = new Rect
85 (
86 middlePosition.x,
87 middlePosition.y,
88 0,
89 0
90 );
91
92 _clippingPosition = _position.Encompass(sourceHandleEdgeCenter).Encompass(destinationHandleEdgeCenter);
93 }
94
95 #endregion
96
97
98 #region Drawing
99
100 protected virtual bool colorIfActive => true;
101
102 public abstract Color color { get; }
103
104 protected override bool dim
105 {
106 get
107 {
108 var dim = BoltCore.Configuration.dimInactiveNodes && !connection.destination.unit.Analysis<UnitAnalysis>(context).isEntered;
109
110 if (BoltCore.Configuration.dimIncompatibleNodes && canvas.isCreatingConnection)
111 {
112 dim = true;
113 }
114
115 return dim;
116 }
117 }
118
119 public override void DrawBackground()
120 {
121 base.DrawBackground();
122
123 BeginDim();
124
125 DrawConnection();
126
127 if (showDroplets)
128 {
129 DrawDroplets();
130 }
131
132 EndDim();
133 }
134
135 protected virtual void DrawConnection()
136 {
137 var color = this.color;
138
139 var sourceWidget = canvas.Widget<IUnitPortWidget>(connection.source);
140 var destinationWidget = canvas.Widget<IUnitPortWidget>(connection.destination);
141
142 var highlight = !canvas.isCreatingConnection && (sourceWidget.isMouseOver || destinationWidget.isMouseOver);
143
144 var willDisconnect = sourceWidget.willDisconnect || destinationWidget.willDisconnect;
145
146 if (willDisconnect)
147 {
148 color = UnitConnectionStyles.disconnectColor;
149 }
150 else if (highlight)
151 {
152 color = UnitConnectionStyles.highlightColor;
153 }
154 else if (colorIfActive)
155 {
156 if (EditorApplication.isPaused)
157 {
158 if (EditorTimeBinding.frame == ConnectionDebugData.lastInvokeFrame)
159 {
160 color = UnitConnectionStyles.activeColor;
161 }
162 }
163 else
164 {
165 color = Color.Lerp(UnitConnectionStyles.activeColor, color, (EditorTimeBinding.time - ConnectionDebugData.lastInvokeTime) / UnitWidget<IUnit>.Styles.invokeFadeDuration);
166 }
167 }
168
169 var thickness = 3;
170
171 GraphGUI.DrawConnection(color, sourceHandleEdgeCenter, destinationHandleEdgeCenter, Edge.Right, Edge.Left, null, Vector2.zero, UnitConnectionStyles.relativeBend, UnitConnectionStyles.minBend, thickness);
172 }
173
174 #endregion
175
176
177 #region Selecting
178
179 public override bool canSelect => false;
180
181 #endregion
182
183
184 #region Dragging
185
186 public override bool canDrag => false;
187
188 #endregion
189
190
191 #region Deleting
192
193 public override bool canDelete => true;
194
195 #endregion
196
197
198 #region Droplets
199
200 private readonly List<float> droplets = new List<float>();
201
202 private float dropTime;
203
204 private float lastInvokeTime;
205
206 private const float handleAlignmentMargin = 0.1f;
207
208 protected virtual bool showDroplets => true;
209
210 protected abstract Vector2 GetDropletSize();
211
212 protected abstract void DrawDroplet(Rect position);
213
214 protected virtual void DrawDroplets()
215 {
216 foreach (var droplet in droplets)
217 {
218 Vector2 position;
219
220 if (droplet < handleAlignmentMargin)
221 {
222 var t = droplet / handleAlignmentMargin;
223 position = Vector2.Lerp(sourceHandlePosition.center, sourceHandleEdgeCenter, t);
224 }
225 else if (droplet > 1 - handleAlignmentMargin)
226 {
227 var t = (droplet - (1 - handleAlignmentMargin)) / handleAlignmentMargin;
228 position = Vector2.Lerp(destinationHandleEdgeCenter, destinationHandlePosition.center, t);
229 }
230 else
231 {
232 var t = (droplet - handleAlignmentMargin) / (1 - 2 * handleAlignmentMargin);
233 position = GraphGUI.GetPointOnConnection(t, sourceHandleEdgeCenter, destinationHandleEdgeCenter, Edge.Right, Edge.Left, UnitConnectionStyles.relativeBend, UnitConnectionStyles.minBend);
234 }
235
236 var size = GetDropletSize();
237
238 using (LudiqGUI.color.Override(GUI.color * color))
239 {
240 DrawDroplet(new Rect(position.x - size.x / 2, position.y - size.y / 2, size.x, size.y));
241 }
242 }
243 }
244
245 #endregion
246 }
247}