1 using Microsoft.Xna.Framework;
2 using Microsoft.Xna.Framework.Graphics;
4 using System.Collections.Generic;
9 partial class Connection
12 private static Sprite connector;
13 private static Sprite wireVertical;
14 private static Sprite connectionSprite;
15 private static Sprite connectionSpriteHighlight;
16 private static List<Sprite> screwSprites;
18 private Color flashColor;
19 private float flashDuration = 1.5f;
24 private static float ConnectionSpriteSize => 35.0f * GUI.Scale;
35 int x = panelRect.X, y = panelRect.Y;
36 int width = panelRect.Width, height = panelRect.Height;
40 int totalWireCount = 0;
43 totalWireCount += c.Wires.Count;
46 Wire equippedWire =
null;
55 Wire wireComponent = item.GetComponent<
Wire>();
56 if (wireComponent !=
null)
58 equippedWire = wireComponent;
68 tooltip = (Vector2.Zero,
string.Empty);
71 for (
int i = 0; i < 2; i++)
73 Vector2 rightPos = GetRightPos(x, y, width);
74 Vector2 leftPos = GetLeftPos(x, y);
76 Vector2 rightWirePos =
new Vector2(x + width - 5 * GUI.Scale, y + 30 * GUI.Scale);
77 Vector2 leftWirePos =
new Vector2(x + 5 * GUI.Scale, y + 30 * GUI.Scale);
79 int wireInterval = (height - (int)(20 * GUI.Scale)) / Math.Max(totalWireCount, 1);
80 int connectorIntervalLeft = GetConnectorIntervalLeft(height, panel);
81 int connectorIntervalRight = GetConnectorIntervalRight(height, panel);
103 Vector2 position = c.IsOutput ? rightPos : leftPos;
108 if (!tooltipText.IsNullOrEmpty())
113 tooltip = (position, tooltipText);
123 c.DrawConnection(spriteBatch, panel, rightPos, GetOutputLabelPosition(rightPos, panel, c));
127 c.DrawWires(spriteBatch, panel, rightPos, rightWirePos, mouseInRect, equippedWire, wireInterval);
129 rightPos.Y += connectorIntervalLeft;
130 rightWirePos.Y += c.Wires.Count * wireInterval;
136 c.DrawConnection(spriteBatch, panel, leftPos, GetInputLabelPosition(leftPos, panel, c));
140 c.DrawWires(spriteBatch, panel, leftPos, leftWirePos, mouseInRect, equippedWire, wireInterval);
142 leftPos.Y += connectorIntervalRight;
143 leftWirePos.Y += c.Wires.Count * wireInterval;
152 Vector2 wireDragPos =
new Vector2(
155 DrawWire(spriteBatch,
DraggingConnected, wireDragPos,
new Vector2(x + width / 2, y + height - 10),
null, panel,
"");
180 panel.
Item.CreateClientEvent(panel);
191 if (panel.
Connections.Find(c => c.Wires.Contains(equippedWire)) ==
null)
193 DrawWire(spriteBatch, equippedWire,
new Vector2(x + width / 2, y + height - 150 * GUI.Scale),
194 new Vector2(x + width / 2, y + height),
214 LocalizedString label = recipient ==
null ?
"" : recipient.item.Name + $
" ({recipient.DisplayName})";
215 if (wire.
Locked) { label +=
"\n" + TextManager.Get(
"ConnectionLocked"); }
216 DrawWire(spriteBatch, wire,
new Vector2(x, y + height - 100 * GUI.Scale),
217 new Vector2(x, y + height),
232 Color highlightColor = Color.Transparent;
235 highlightColor = VisualizeSignal(0.0f, highlightColor, Color.Red);
239 highlightColor = VisualizeSignal(c.LastReceivedSignal.TimeSinceCreated, highlightColor, Color.LightGreen);
240 highlightColor = VisualizeSignal(c.LastSentSignal.TimeSinceCreated, highlightColor, Color.Orange);
244 if (!toolTipText.IsNullOrEmpty())
246 var glowSprite = GUIStyle.UIGlowCircular.
Value.Sprite;
247 glowSprite.Draw(spriteBatch, position, highlightColor, glowSprite.size / 2,
248 scale: 45.0f / glowSprite.size.X * scale);
251 tooltip = toolTipText;
253 static Color VisualizeSignal(
double timeSinceCreated, Color defaultColor, Color color)
255 if (timeSinceCreated < 1.0f)
257 float pulseAmount = (MathF.Sin((
float)Timing.TotalTimeUnpaused * 10.0f) + 3.0f) / 4.0f;
258 Color targetColor = Color.Lerp(defaultColor, color, pulseAmount);
259 return Color.Lerp(targetColor, defaultColor, (
float)timeSinceCreated);
265 private void DrawConnection(SpriteBatch spriteBatch,
ConnectionPanel panel, Vector2 position, Vector2 labelPos)
270 if (GUIStyle.GetComponentStyle(
"ConnectionPanelLabel")?.Sprites.Values.First().First() is
UISprite labelSprite)
272 Rectangle labelArea = GetLabelArea(labelPos, text);
273 labelSprite.Draw(spriteBatch, labelArea,
IsPower ? GUIStyle.Red : Color.SteelBlue);
276 GUI.DrawString(spriteBatch, labelPos + Vector2.UnitY, text, Color.Black * 0.8f, font: GUIStyle.SmallFont);
277 GUI.DrawString(spriteBatch, labelPos, text, GUIStyle.TextColorBright, font: GUIStyle.SmallFont);
279 float connectorSpriteScale = ConnectionSpriteSize / connectionSprite.SourceRect.Width;
281 connectionSprite.Draw(spriteBatch, position, scale: connectorSpriteScale);
285 private void DrawWires(SpriteBatch spriteBatch,
ConnectionPanel panel, Vector2 position, Vector2 wirePosition,
bool mouseIn, Wire equippedWire,
float wireInterval)
287 float connectorSpriteScale = ConnectionSpriteSize / connectionSprite.SourceRect.Width;
289 foreach (var wire
in wires)
292 if (wire.HiddenInGame && Screen.Selected == GameMain.GameScreen) {
continue; }
294 Connection recipient = wire.OtherConnection(
this);
295 LocalizedString label;
296 if (wire.Item.IsLayerHidden)
298 label = TextManager.Get(
"ConnectionLocked");
302 label = recipient ==
null ?
"" : recipient.item.Name + $
" ({recipient.DisplayName})";
303 if (wire.Locked) { label +=
"\n" + TextManager.Get(
"ConnectionLocked"); }
306 DrawWire(spriteBatch, wire, position, wirePosition, equippedWire, panel, label);
308 wirePosition.Y += wireInterval;
311 bool isMouseOn = Vector2.Distance(position, PlayerInput.MousePosition) < (20.0f * GUI.Scale);
314 connectionSpriteHighlight.Draw(spriteBatch, position, scale: connectorSpriteScale);
320 if (!PlayerInput.PrimaryMouseButtonHeld())
322 if ((GameMain.NetworkMember !=
null || panel.CheckCharacterSuccess(
Character.Controlled)) &&
338 if (GameMain.Client !=
null)
340 panel.Item.CreateClientEvent(panel);
349 int flashCycleCount = (int)Math.Max(flashDuration, 1);
350 float flashCycleDuration = flashDuration / flashCycleCount;
354 connectionSpriteHighlight.
Draw(spriteBatch, position,
355 flashColor * (
float)Math.Sin(
FlashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f), scale: connectorSpriteScale);
360 int screwIndex = (int)Math.Floor(position.Y / 30.0f) % screwSprites.Count;
361 screwSprites[screwIndex].Draw(spriteBatch, position, scale: connectorSpriteScale);
365 public void Flash(Color? color =
null,
float flashDuration = 1.5f)
368 this.flashDuration = flashDuration;
369 flashColor = (color ==
null) ? GUIStyle.Red : (Color)color;
394 if (lastSignalToolTip.signal == signal.value && !lastSignalToolTip.tooltip.IsNullOrEmpty()) {
return lastSignalToolTip.tooltip; }
395 lastSignalToolTip = (signal.value, TextManager.GetWithVariable(textTag,
"[signal]", signal.value));
396 return lastSignalToolTip.tooltip;
401 if (item.GetComponent<Powered>() is Powered powered)
405 if (powered.CurrPowerConsumption < 0)
407 return getPowerTooltip(-(
int)powered.CurrPowerConsumption,
"reactoroutput");
409 else if (powered is PowerTransfer || powered is PowerContainer)
411 return getPowerTooltip((
int)(
Grid?.Power ?? 0),
"reactoroutput");
416 float powerConsumption = powered.GetCurrentPowerConsumption(
this);
417 if (!MathUtils.NearlyEqual((
int)powerConsumption, 0.0f))
419 return getPowerTooltip((
int)powerConsumption,
"reactorload");
425 LocalizedString getPowerTooltip(
int powerValue,
string textTag)
427 if (lastPowerToolTip.powerValue == powerValue && !lastPowerToolTip.tooltip.IsNullOrEmpty()) {
return lastPowerToolTip.tooltip; }
428 lastPowerToolTip = (powerValue, TextManager.GetWithVariable(textTag,
"[kw]", powerValue.ToString()));
429 return lastPowerToolTip.tooltip;
435 private static void DrawWire(SpriteBatch spriteBatch, Wire wire, Vector2 end, Vector2 start, Wire equippedWire,
ConnectionPanel panel, LocalizedString label)
437 int textX = (int)start.X;
443 bool canDrag = equippedWire ==
null || equippedWire == wire;
445 float alpha = canDrag ? 1.0f : 0.5f;
449 GUI.MouseOn is not GUIDragHandle &&
450 ((PlayerInput.MousePosition.X > Math.Min(start.X, end.X) &&
451 PlayerInput.MousePosition.X < Math.Max(start.X, end.X) &&
452 MathUtils.LineToPointDistanceSquared(start, end, PlayerInput.MousePosition) < 36) ||
453 Vector2.Distance(end, PlayerInput.MousePosition) < 20.0f ||
454 new Rectangle((start.X < end.X) ? textX - 100 : textX, (
int)start.Y - 5, 100, 14).Contains(PlayerInput.MousePosition));
456 if (!label.IsNullOrEmpty())
458 if (start.Y > panel.GuiFrame.Rect.Bottom - 1.0f)
461 GUIStyle.Font.DrawString(spriteBatch, label, start + Vector2.UnitY * 20 * GUI.Scale, Color.White, 45.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
465 GUI.DrawString(spriteBatch,
466 new Vector2(start.X < end.X ? textX - GUIStyle.SmallFont.MeasureString(label).X : textX, start.Y - 5.0f),
468 wire.Locked ? GUIStyle.TextColorDim : (mouseOn ? Wire.higlightColor : GUIStyle.TextColorNormal), Color.Black * 0.9f,
469 3, GUIStyle.SmallFont);
473 var wireEnd = end + Vector2.Normalize(start - end) * 30.0f * GUI.Scale;
475 float dist = Vector2.Distance(start, wireEnd);
477 float wireWidth = 12 * GUI.Scale;
478 float highlight = 5 * GUI.Scale;
481 spriteBatch.Draw(wireVertical.Texture,
new Rectangle(wireEnd.ToPoint(),
new Point((
int)(wireWidth + highlight), (
int)dist)), wireVertical.SourceRect,
483 MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2,
484 new Vector2(wireVertical.size.X / 2, 0),
488 spriteBatch.Draw(wireVertical.Texture,
new Rectangle(wireEnd.ToPoint(),
new Point((
int)wireWidth, (
int)dist)), wireVertical.SourceRect,
489 wire.Item.Color * alpha,
490 MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2,
491 new Vector2(wireVertical.size.X / 2, 0),
495 float connectorScale = wireWidth / (float)wireVertical.SourceRect.Width;
497 connector.Draw(spriteBatch, end, Color.White, connector.Origin, MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2, scale: connectorScale);
505 bool allowRewiring = GameMain.NetworkMember?.ServerSettings ==
null || GameMain.NetworkMember.ServerSettings.AllowRewiring || panel.AlwaysAllowRewiring;
506 if (allowRewiring && (!wire.Locked && !wire.Item.IsLayerHidden && !panel.Locked && !panel.TemporarilyLocked || Screen.Selected == GameMain.SubEditorScreen))
518 int x = panelRect.X, y = panelRect.Y;
519 Vector2 rightPos = GetRightPos(x, y, panelRect.Width);
520 Vector2 leftPos = GetLeftPos(x, y);
521 int connectorIntervalLeft = GetConnectorIntervalLeft(panelRect.Height, panel);
522 int connectorIntervalRight = GetConnectorIntervalRight(panelRect.Height, panel);
523 newRectSize = panelRect.Size;
526 float rightMostInput = panelRect.Center.X;
527 float leftMostOutput = panelRect.Center.X;
528 foreach (var c
in panel.Connections)
532 var labelArea = GetLabelArea(GetOutputLabelPosition(rightPos, panel, c), c.DisplayName.Value.ToUpperInvariant());
533 leftMostOutput = Math.Min(leftMostOutput, labelArea.X);
534 rightPos.Y += connectorIntervalLeft;
538 var labelArea = GetLabelArea(GetInputLabelPosition(leftPos, panel, c), c.DisplayName.Value.ToUpperInvariant());
539 rightMostInput = Math.Max(rightMostInput, labelArea.Right);
540 leftPos.Y += connectorIntervalRight;
543 if (leftMostOutput < rightMostInput)
545 newRectSize +=
new Point((
int)(rightMostInput - leftMostOutput) + GUI.IntScale(15), 0);
549 while (GetConnectorIntervalLeft(newRectSize.Y, panel) < ConnectionSpriteSize ||
550 GetConnectorIntervalRight(newRectSize.Y, panel) < ConnectionSpriteSize)
554 return newRectSize.X != panel.GuiFrame.Rect.Width || newRectSize.Y > panel.GuiFrame.Rect.Height;
560 connectorPosition.X + 25 * GUI.Scale,
561 connectorPosition.Y - GUIStyle.SmallFont.MeasureString(connection.DisplayName.ToUpper()).Y / 2);
567 connectorPosition.X - 25 * GUI.Scale - GUIStyle.SmallFont.MeasureString(connection.DisplayName.ToUpper()).X,
568 connectorPosition.Y - GUIStyle.SmallFont.MeasureString(connection.DisplayName.ToUpper()).Y / 2);
571 private static Rectangle GetLabelArea(Vector2 labelPos,
string text)
573 Vector2 textSize = GUIStyle.SmallFont.MeasureString(text);
575 labelArea.Inflate(GUI.IntScale(10), GUI.IntScale(3));
579 private static Vector2 GetLeftPos(
int x,
int y)
581 return new Vector2(x + 80 * GUI.Scale, y + 60 * GUI.Scale);
584 private static Vector2 GetRightPos(
int x,
int y,
int width)
586 return new Vector2(x + width - 80 * GUI.Scale, y + 60 * GUI.Scale);
589 private static int GetConnectorIntervalLeft(
int height,
ConnectionPanel panel)
591 return (height - GUI.IntScale(60)) / Math.Max(panel.Connections.Count(c => c.IsOutput), 1);
594 private static int GetConnectorIntervalRight(
int height,
ConnectionPanel panel)
596 return (height - GUI.IntScale(60)) / Math.Max(panel.Connections.Count(c => !c.IsOutput), 1);
static Character? Controlled
IEnumerable< Item >?? HeldItems
Items the character has in their hand slots. Doesn't return nulls and only returns items held in both...
static SubEditorScreen SubEditorScreen
static GameScreen GameScreen
static NetworkMember NetworkMember
static readonly List< Item > DraggingItems
Inventory ParentInventory
IReadOnlyCollection< Wire > Wires
bool WireSlotsAvailable()
static bool CheckConnectionLabelOverlap(ConnectionPanel panel, out Point newRectSize)
readonly LocalizedString DisplayName
void ConnectWire(Wire wire)
ConnectionPanel ConnectionPanel
void Flash(Color? color=null, float flashDuration=1.5f)
static Wire DraggingConnected
Signal LastReceivedSignal
static void DrawConnections(SpriteBatch spriteBatch, ConnectionPanel panel, Rectangle dragArea, Character character, out(Vector2 tooltipPos, LocalizedString text) tooltip)
static void DrawConnectionDebugInfo(SpriteBatch spriteBatch, Connection c, Vector2 position, float scale, out LocalizedString tooltip)
void UpdateFlashTimer(float deltaTime)
readonly int MaxPlayerConnectableWires
Connection(ContentXElement element, ConnectionPanel connectionPanel, IdRemap idRemap)
static Wire HighlightedWire
readonly List< Connection > Connections
readonly HashSet< Wire > DisconnectedWires
Wires that have been disconnected from the panel, but not removed completely (visible at the bottom o...
static bool ShouldDebugDrawWiring
bool??? TemporarilyLocked
bool AlwaysAllowRewiring
Allows rewiring the connection panel despite rewiring being disabled on a server
void TriggerRewiringSound()
bool CheckCharacterSuccess(Character character)
Check if the character manages to succesfully rewire the panel, and if not, apply OnFailure effects
void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth=-1, Color? overrideColor=null)
void RemoveConnection(Item item)
bool TryConnect(Connection newConnection, bool addNode=true, bool sendNetworkEvent=false)
Tries to add the given connection to this wire. Note that this only affects the wire - adding the wir...
void ClearConnections(Character user=null)
bool IsConnectedTo(Item item)
Connection OtherConnection(Connection connection)
Submarine(SubmarineInfo info, bool showErrorMessages=true, Func< Submarine, List< MapEntity >> loadEntities=null, IdRemap linkedRemap=null)