Client LuaCsForBarotrauma
BarotraumaShared/SharedSource/CircuitBox/CircuitBoxNode.cs
1 #nullable enable
2 
3 using System;
4 using System.Collections.Generic;
5 using System.Collections.Immutable;
7 using Microsoft.Xna.Framework;
8 
9 namespace Barotrauma
10 {
11  internal partial class CircuitBoxNode : CircuitBoxSelectable
12  {
13  public Vector2 Size;
14  public RectangleF Rect;
15  private Vector2 position;
16 
17  public virtual bool IsResizable => false;
18 
19  public Vector2 Position
20  {
21  get => position;
22  set
23  {
24  const float clampSize = CircuitBoxSizes.PlayableAreaSize / 2f;
25 
26  position = new Vector2(Math.Clamp(value.X, -clampSize, clampSize),
27  Math.Clamp(value.Y, -clampSize, clampSize));
28  UpdatePositions();
29  }
30  }
31 
32  public ImmutableArray<CircuitBoxConnection> Connectors = ImmutableArray<CircuitBoxConnection>.Empty;
33 
34  public static float Opacity = 0.8f;
35 
36  public readonly CircuitBox CircuitBox;
37 
38  public CircuitBoxNode(CircuitBox circuitBox)
39  {
40  CircuitBox = circuitBox;
41  }
42 
43  public (Vector2 Size, Vector2 Pos) ResizeBy(CircuitBoxResizeDirection directions, Vector2 amount)
44  {
45  Vector2 newSize = Size;
46  Vector2 newPos = Position;
47  amount.Y = -amount.Y;
48 
49  if (directions.HasFlag(CircuitBoxResizeDirection.Down))
50  {
51  newSize.Y += amount.Y;
52  newSize.Y = Math.Max(newSize.Y, CircuitBoxLabelNode.MinSize.Y);
53  newPos = new Vector2(newPos.X, newPos.Y - (newSize.Y - Size.Y) / 2f);
54  }
55 
56  if (directions.HasFlag(CircuitBoxResizeDirection.Right))
57  {
58  newSize.X += amount.X;
59  newSize.X = Math.Max(newSize.X, CircuitBoxLabelNode.MinSize.X);
60  newPos = new Vector2(newPos.X + (newSize.X - Size.X) / 2f, newPos.Y);
61  }
62 
63  if (directions.HasFlag(CircuitBoxResizeDirection.Left))
64  {
65  newSize.X -= amount.X;
66  newSize.X = Math.Max(newSize.X, CircuitBoxLabelNode.MinSize.X);
67  newPos = new Vector2(newPos.X + (Size.X - newSize.X) / 2f, newPos.Y);
68  }
69 
70  return (newSize, newPos);
71  }
72 
73  public void ApplyResize(Vector2 newSize, Vector2 newPos)
74  {
75  if (!MathUtils.IsValid(newSize)) { return; }
76  Size = newSize;
77  Position = newPos;
78  UpdatePositions();
79 #if CLIENT
80  OnResized(DrawRect);
81 #endif
82  }
83 
84  public static Vector2 CalculateSize(IReadOnlyList<CircuitBoxConnection> conns)
85  {
86  Vector2 leftSize = Vector2.Zero,
87  rightSize = Vector2.Zero;
88 
89  foreach (var c in conns)
90  {
91  if (c.IsOutput)
92  {
93  rightSize.X = MathF.Max(rightSize.X, c.Length);
94  }
95  else
96  {
97  leftSize.X = MathF.Max(leftSize.X, c.Length);
98  }
99 
100  if (c.IsOutput)
101  {
102  rightSize.Y += CircuitBoxConnection.Size;
103  }
104  else
105  {
106  leftSize.Y += CircuitBoxConnection.Size;
107  }
108  }
109 
110  return new Vector2(leftSize.X + CircuitBoxSizes.NodeInitialPadding + rightSize.X, CircuitBoxSizes.NodeInitialPadding + MathF.Max(leftSize.Y, rightSize.Y));
111  }
112 
113  protected void UpdatePositions()
114  {
115  Vector2 rectStart = Position - Size / 2f;
116  Vector2 rectSize = Size;
117  rectSize.Y += CircuitBoxSizes.NodeHeaderHeight;
118  Rect = new RectangleF(rectStart, rectSize);
119 
120 #if CLIENT
121  UpdateDrawRects();
122 #endif
123 
124  int leftIndex = 0,
125  rightIndex = 0;
126 
127  int inputCount = 0,
128  outputCount = 0;
129 
130  foreach (var c in Connectors)
131  {
132  if (c.IsOutput)
133  {
134  outputCount++;
135  }
136  else
137  {
138  inputCount++;
139  }
140  }
141 
142  Vector2 drawPos = Position;
143  drawPos.Y = -drawPos.Y;
144 
145  foreach (var c in Connectors)
146  {
147  bool isOutput = c.IsOutput;
148 
149  int yIndex = isOutput ? rightIndex : leftIndex;
150  int count = isOutput ? outputCount : inputCount;
151 
152  float totalHeight = (count * CircuitBoxConnection.Size) / 2f;
153  float y = (yIndex * CircuitBoxConnection.Size) - totalHeight;
154 
155  float halfWidth = Rect.Width / 2f - CircuitBoxConnection.Size / 2f;
156 
157  halfWidth -= 16f;
158 
159  float xOffset = c.IsOutput ? halfWidth : -halfWidth;
160 
161  Vector2 inputPos = drawPos + new Vector2(xOffset, y + c.Rect.Height / 2f);
162  c.Position = inputPos;
163 
164  if (isOutput)
165  {
166  rightIndex++;
167  }
168  else
169  {
170  leftIndex++;
171  }
172  }
173  }
174  }
175 }