(61d00a474) v0.9.7.1

This commit is contained in:
Regalis
2020-03-04 13:04:10 +01:00
parent 3c50efa5c9
commit 3c09ebe02f
5086 changed files with 786063 additions and 295871 deletions
@@ -0,0 +1,391 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma.Items.Components
{
partial class Connection
{
//private static Texture2D panelTexture;
private static Sprite connector;
private static Sprite wireVertical;
private static Sprite connectionSprite;
private static Sprite connectionSpriteHighlight;
private static List<Sprite> screwSprites;
private Color flashColor;
private float flashDuration = 1.5f;
public float FlashTimer { get; private set; }
public static Wire DraggingConnected { get; private set; }
public static void DrawConnections(SpriteBatch spriteBatch, ConnectionPanel panel, Character character)
{
Rectangle panelRect = panel.GuiFrame.Rect;
int x = panelRect.X, y = panelRect.Y;
int width = panelRect.Width, height = panelRect.Height;
Vector2 scale = new Vector2(GUI.Scale);
if (panel.GuiFrame.RectTransform.MaxSize.X < int.MaxValue)
{
scale.X = panel.GuiFrame.RectTransform.MaxSize.X / panel.GuiFrame.Rect.Width;
}
if (panel.GuiFrame.RectTransform.MaxSize.Y < int.MaxValue)
{
scale.Y = panel.GuiFrame.RectTransform.MaxSize.Y / panel.GuiFrame.Rect.Height;
}
bool mouseInRect = panelRect.Contains(PlayerInput.MousePosition);
int totalWireCount = 0;
foreach (Connection c in panel.Connections)
{
totalWireCount += c.Wires.Count(w => w != null);
}
Wire equippedWire = null;
bool allowRewiring = GameMain.NetworkMember?.ServerSettings == null || GameMain.NetworkMember.ServerSettings.AllowRewiring;
if (allowRewiring && (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
{
//if the Character using the panel has a wire item equipped
//and the wire hasn't been connected yet, draw it on the panel
for (int i = 0; i < character.SelectedItems.Length; i++)
{
Item selectedItem = character.SelectedItems[i];
if (selectedItem == null) { continue; }
Wire wireComponent = selectedItem.GetComponent<Wire>();
if (wireComponent != null)
{
equippedWire = wireComponent;
}
}
}
//two passes: first the connector, then the wires to get the wires to render in front
for (int i = 0; i < 2; i++)
{
Vector2 rightPos = new Vector2(x + width - 80 * scale.X, y + 60 * scale.Y);
Vector2 leftPos = new Vector2(x + 80 * scale.X, y + 60 * scale.Y);
Vector2 rightWirePos = new Vector2(x + width - 5 * scale.X, y + 30 * scale.Y);
Vector2 leftWirePos = new Vector2(x + 5 * scale.X, y + 30 * scale.Y);
int wireInterval = (height - (int)(20 * scale.Y)) / Math.Max(totalWireCount, 1);
int connectorIntervalLeft = (height - (int)(100 * scale.Y)) / Math.Max(panel.Connections.Count(c => c.IsOutput), 1);
int connectorIntervalRight = (height - (int)(100 * scale.Y)) / Math.Max(panel.Connections.Count(c => !c.IsOutput), 1);
foreach (Connection c in panel.Connections)
{
//if dragging a wire, let the Inventory know so that the wire can be
//dropped or dragged from the panel to the players inventory
if (DraggingConnected != null && i == 1)
{
//the wire can only be dragged out if it's not connected to anything at the other end
if (Screen.Selected == GameMain.SubEditorScreen ||
(DraggingConnected.Connections[0] == null && DraggingConnected.Connections[1] == null) ||
(DraggingConnected.Connections.Contains(c) && DraggingConnected.Connections.Contains(null)))
{
int linkIndex = c.FindWireIndex(DraggingConnected.Item);
if (linkIndex > -1 || panel.DisconnectedWires.Contains(DraggingConnected))
{
Inventory.draggingItem = DraggingConnected.Item;
}
}
}
//outputs are drawn at the right side of the panel, inputs at the left
if (c.IsOutput)
{
if (i == 0)
{
c.DrawConnection(spriteBatch, panel, rightPos,
new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.DisplayName.ToUpper()).X - 25 * panel.Scale, rightPos.Y + 5 * panel.Scale),
scale);
}
else
{
c.DrawWires(spriteBatch, panel, rightPos, rightWirePos, mouseInRect, equippedWire, wireInterval);
}
rightPos.Y += connectorIntervalLeft;
rightWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
}
else
{
if (i == 0)
{
c.DrawConnection(spriteBatch, panel, leftPos,
new Vector2(leftPos.X + 25 * panel.Scale, leftPos.Y - 5 * panel.Scale - GUI.SmallFont.MeasureString(c.DisplayName.ToUpper()).Y),
scale);
}
else
{
c.DrawWires(spriteBatch, panel, leftPos, leftWirePos, mouseInRect, equippedWire, wireInterval);
}
leftPos.Y += connectorIntervalRight;
leftWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
}
}
}
if (DraggingConnected != null)
{
if (mouseInRect)
{
DrawWire(spriteBatch, DraggingConnected, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height - 10), null, panel, "");
}
panel.TriggerRewiringSound();
if (!PlayerInput.PrimaryMouseButtonHeld())
{
if (GameMain.NetworkMember != null || panel.CheckCharacterSuccess(character))
{
if (DraggingConnected.Connections[0]?.ConnectionPanel == panel ||
DraggingConnected.Connections[1]?.ConnectionPanel == panel)
{
DraggingConnected.RemoveConnection(panel.Item);
if (DraggingConnected.Item.ParentInventory == null)
{
panel.DisconnectedWires.Add(DraggingConnected);
}
else if (DraggingConnected.Connections[0] == null && DraggingConnected.Connections[1] == null)
{
DraggingConnected.ClearConnections(user: Character.Controlled);
}
}
}
if (GameMain.Client != null)
{
panel.Item.CreateClientEvent(panel);
}
DraggingConnected = null;
}
}
//if the Character using the panel has a wire item equipped
//and the wire hasn't been connected yet, draw it on the panel
if (equippedWire != null && (DraggingConnected != equippedWire || !mouseInRect))
{
if (panel.Connections.Find(c => c.Wires.Contains(equippedWire)) == null)
{
DrawWire(spriteBatch, equippedWire, new Vector2(x + width / 2, y + height - 150 * GUI.Scale),
new Vector2(x + width / 2, y + height),
null, panel, "");
if (DraggingConnected == equippedWire) { Inventory.draggingItem = equippedWire.Item; }
}
}
float step = (width * 0.75f) / panel.DisconnectedWires.Count();
x = (int)(x + width / 2 - step * (panel.DisconnectedWires.Count() - 1) / 2);
foreach (Wire wire in panel.DisconnectedWires)
{
if (wire == DraggingConnected && mouseInRect) { continue; }
Connection recipient = wire.OtherConnection(null);
string label = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
if (wire.Locked) { label += "\n" + TextManager.Get("ConnectionLocked"); }
DrawWire(spriteBatch, wire, new Vector2(x, y + height - 100 * GUI.Scale),
new Vector2(x, y + height),
null, panel, label);
x += (int)step;
}
//stop dragging a wire item if the cursor is within any connection panel
//(so we don't drop the item when dropping the wire on a connection)
if (mouseInRect || (GUI.MouseOn?.UserData is ConnectionPanel && GUI.MouseOn.MouseRect.Contains(PlayerInput.MousePosition)))
{
Inventory.draggingItem = null;
}
}
private void DrawConnection(SpriteBatch spriteBatch, ConnectionPanel panel, Vector2 position, Vector2 labelPos, Vector2 scale)
{
string text = DisplayName.ToUpper();
Vector2 textSize = GUI.SmallFont.MeasureString(text);
//nasty
var labelSprite = GUI.Style.GetComponentStyle("ConnectionPanelLabel")?.Sprites.Values.First().First();
if (labelSprite != null)
{
Rectangle labelArea = new Rectangle(labelPos.ToPoint(), textSize.ToPoint());
labelArea.Inflate(10 * scale.X, 3 * scale.Y);
labelSprite.Draw(spriteBatch, labelArea, IsPower ? GUI.Style.Red : Color.SteelBlue);
}
GUI.DrawString(spriteBatch, labelPos + Vector2.UnitY, text, Color.Black * 0.8f, font: GUI.SmallFont);
GUI.DrawString(spriteBatch, labelPos, text, GUI.Style.TextColorBright, font: GUI.SmallFont);
float connectorSpriteScale = (35.0f / connectionSprite.SourceRect.Width) * panel.Scale;
connectionSprite.Draw(spriteBatch, position, scale: connectorSpriteScale);
}
private void DrawWires(SpriteBatch spriteBatch, ConnectionPanel panel, Vector2 position, Vector2 wirePosition, bool mouseIn, Wire equippedWire, float wireInterval)
{
float connectorSpriteScale = (35.0f / connectionSprite.SourceRect.Width) * panel.Scale;
for (int i = 0; i < MaxLinked; i++)
{
if (wires[i] == null || wires[i].Hidden || (DraggingConnected == wires[i] && (mouseIn || Screen.Selected == GameMain.SubEditorScreen))) { continue; }
Connection recipient = wires[i].OtherConnection(this);
string label = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
if (wires[i].Locked) { label += "\n" + TextManager.Get("ConnectionLocked"); }
DrawWire(spriteBatch, wires[i], position, wirePosition, equippedWire, panel, label);
wirePosition.Y += wireInterval;
}
if (DraggingConnected != null && Vector2.Distance(position, PlayerInput.MousePosition) < (20.0f * GUI.Scale))
{
connectionSpriteHighlight.Draw(spriteBatch, position, scale: connectorSpriteScale);
if (!PlayerInput.PrimaryMouseButtonHeld())
{
if (GameMain.NetworkMember != null || panel.CheckCharacterSuccess(Character.Controlled))
{
//find an empty cell for the new connection
int index = FindEmptyIndex();
if (index > -1 && !Wires.Contains(DraggingConnected))
{
bool alreadyConnected = DraggingConnected.IsConnectedTo(panel.Item);
DraggingConnected.RemoveConnection(panel.Item);
if (DraggingConnected.Connect(this, !alreadyConnected, true))
{
var otherConnection = DraggingConnected.OtherConnection(this);
SetWire(index, DraggingConnected);
}
}
}
if (GameMain.Client != null)
{
panel.Item.CreateClientEvent(panel);
}
DraggingConnected = null;
}
}
if (FlashTimer > 0.0f)
{
//the number of flashes depends on the duration, 1 flash per 1 full second
int flashCycleCount = (int)Math.Max(flashDuration, 1);
float flashCycleDuration = flashDuration / flashCycleCount;
//MathHelper.Pi * 0.8f -> the curve goes from 144 deg to 0,
//i.e. quickly bumps up from almost full brightness to full and then fades out
connectionSpriteHighlight.Draw(spriteBatch, position,
flashColor * (float)Math.Sin(FlashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f), scale: connectorSpriteScale);
}
if (Wires.Any(w => w != null && w != DraggingConnected))
{
int screwIndex = (int)Math.Floor(position.Y / 30.0f) % screwSprites.Count;
screwSprites[screwIndex].Draw(spriteBatch, position, scale: connectorSpriteScale);
}
}
public void Flash(Color? color = null, float flashDuration = 1.5f)
{
FlashTimer = flashDuration;
this.flashDuration = flashDuration;
flashColor = (color == null) ? GUI.Style.Red : (Color)color;
}
public void UpdateFlashTimer(float deltaTime)
{
if (FlashTimer <= 0) return;
FlashTimer -= deltaTime;
}
private static void DrawWire(SpriteBatch spriteBatch, Wire wire, Vector2 end, Vector2 start, Wire equippedWire, ConnectionPanel panel, string label)
{
int textX = (int)start.X;
if (start.X < end.X)
textX -= 10;
else
textX += 10;
bool canDrag = equippedWire == null || equippedWire == wire;
float alpha = canDrag ? 1.0f : 0.5f;
bool mouseOn =
canDrag &&
((PlayerInput.MousePosition.X > Math.Min(start.X, end.X) &&
PlayerInput.MousePosition.X < Math.Max(start.X, end.X) &&
MathUtils.LineToPointDistance(start, end, PlayerInput.MousePosition) < 6) ||
Vector2.Distance(end, PlayerInput.MousePosition) < 20.0f ||
new Rectangle((start.X < end.X) ? textX - 100 : textX, (int)start.Y - 5, 100, 14).Contains(PlayerInput.MousePosition));
if (!string.IsNullOrEmpty(label))
{
if (start.Y > panel.GuiFrame.Rect.Bottom - 1.0f)
{
//wire at the bottom of the panel -> draw the text below the panel, tilted 45 degrees
GUI.Font.DrawString(spriteBatch, label, start + Vector2.UnitY * 20 * GUI.Scale, Color.White, 45.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
}
else
{
GUI.DrawString(spriteBatch,
new Vector2(start.X < end.X ? textX - GUI.SmallFont.MeasureString(label).X : textX, start.Y - 5.0f),
label,
wire.Locked ? GUI.Style.TextColorDim : (mouseOn ? Wire.higlightColor : GUI.Style.TextColor), Color.Black * 0.9f,
3, GUI.SmallFont);
}
}
var wireEnd = end + Vector2.Normalize(start - end) * 30.0f * panel.Scale;
float dist = Vector2.Distance(start, wireEnd);
float wireWidth = 12 * panel.Scale;
float highlight = 5 * panel.Scale;
if (mouseOn)
{
spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point((int)(wireWidth + highlight), (int)dist)), wireVertical.SourceRect,
Wire.higlightColor,
MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2,
new Vector2(wireVertical.size.X / 2, 0), // point in line about which to rotate
SpriteEffects.None,
0.0f);
}
spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point((int)wireWidth, (int)dist)), wireVertical.SourceRect,
wire.Item.Color * alpha,
MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2,
new Vector2(wireVertical.size.X / 2, 0), // point in line about which to rotate
SpriteEffects.None,
0.0f);
float connectorScale = wireWidth / (float)wireVertical.SourceRect.Width;
connector.Draw(spriteBatch, end, Color.White, connector.Origin, MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2, scale: connectorScale);
if (DraggingConnected == null && canDrag)
{
if (mouseOn)
{
ConnectionPanel.HighlightedWire = wire;
bool allowRewiring = GameMain.NetworkMember?.ServerSettings == null || GameMain.NetworkMember.ServerSettings.AllowRewiring;
if (allowRewiring && !wire.Locked && (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen))
{
//start dragging the wire
if (PlayerInput.PrimaryMouseButtonHeld()) { DraggingConnected = wire; }
}
}
}
}
}
}
@@ -0,0 +1,231 @@
using Barotrauma.Networking;
using Barotrauma.Sounds;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class ConnectionPanel : ItemComponent, IServerSerializable, IClientSerializable
{
//how long the rewiring sound plays after doing changes to the wiring
const float RewireSoundDuration = 5.0f;
public static Wire HighlightedWire;
private SoundChannel rewireSoundChannel;
private float rewireSoundTimer;
public float Scale
{
get { return GuiFrame.Rect.Width / 400.0f; }
}
partial void InitProjSpecific(XElement element)
{
if (GuiFrame == null) { return; }
new GUICustomComponent(new RectTransform(Vector2.One, GuiFrame.RectTransform), DrawConnections, null)
{
UserData = this
};
}
public void TriggerRewiringSound()
{
rewireSoundTimer = RewireSoundDuration;
}
partial void UpdateProjSpecific(float deltaTime)
{
foreach (Wire wire in DisconnectedWires)
{
if (Rand.Range(0.0f, 500.0f) < 1.0f)
{
SoundPlayer.PlaySound("zap", item.WorldPosition, hullGuess: item.CurrentHull);
Vector2 baseVel = new Vector2(0.0f, -100.0f);
for (int i = 0; i < 5; i++)
{
var particle = GameMain.ParticleManager.CreateParticle("spark", item.WorldPosition,
baseVel + Rand.Vector(100.0f), 0.0f, item.CurrentHull);
if (particle != null) { particle.Size *= Rand.Range(0.5f, 1.0f); }
}
}
}
rewireSoundTimer -= deltaTime;
if (user != null && user.SelectedConstruction == item && rewireSoundTimer > 0.0f)
{
if (rewireSoundChannel == null || !rewireSoundChannel.IsPlaying)
{
rewireSoundChannel = SoundPlayer.PlaySound("rewire", item.WorldPosition, hullGuess: item.CurrentHull);
}
}
else
{
rewireSoundChannel?.FadeOutAndDispose();
rewireSoundChannel = null;
rewireSoundTimer = 0.0f;
}
}
public override void Move(Vector2 amount)
{
if (item.Submarine == null || item.Submarine.Loading || Screen.Selected != GameMain.SubEditorScreen) { return; }
MoveConnectedWires(amount);
}
public override bool ShouldDrawHUD(Character character)
{
return character == Character.Controlled && character == user && character.SelectedConstruction == item;
}
public override void AddToGUIUpdateList()
{
GuiFrame?.AddToGUIUpdateList();
}
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
{
if (character != Character.Controlled || character != user || character.SelectedConstruction != item) { return; }
if (HighlightedWire != null)
{
HighlightedWire.Item.IsHighlighted = true;
if (HighlightedWire.Connections[0] != null && HighlightedWire.Connections[0].Item != null) HighlightedWire.Connections[0].Item.IsHighlighted = true;
if (HighlightedWire.Connections[1] != null && HighlightedWire.Connections[1].Item != null) HighlightedWire.Connections[1].Item.IsHighlighted = true;
}
}
private void DrawConnections(SpriteBatch spriteBatch, GUICustomComponent container)
{
if (user != Character.Controlled || user == null) { return; }
HighlightedWire = null;
Connection.DrawConnections(spriteBatch, this, user);
foreach (UISprite sprite in GUI.Style.GetComponentStyle("ConnectionPanelFront").Sprites[GUIComponent.ComponentState.None])
{
sprite.Draw(spriteBatch, GuiFrame.Rect, Color.White, SpriteEffects.None);
}
}
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
if (GameMain.Client.MidRoundSyncing)
{
//delay reading the state until midround syncing is done
//because some of the wires connected to the panel may not exist yet
long msgStartPos = msg.BitPosition;
msg.ReadUInt16(); //user ID
foreach (Connection connection in Connections)
{
for (int i = 0; i < Connection.MaxLinked; i++)
{
msg.ReadUInt16();
}
}
ushort disconnectedWireCount = msg.ReadUInt16();
for (int i = 0; i < disconnectedWireCount; i++)
{
msg.ReadUInt16();
}
int msgLength = (int)(msg.BitPosition - msgStartPos);
msg.BitPosition = (int)msgStartPos;
StartDelayedCorrection(type, msg.ExtractBits(msgLength), sendingTime, waitForMidRoundSync: true);
}
else
{
//don't trigger rewiring sounds if the rewiring is being done by the local user (in that case we'll trigger it locally)
if (Character.Controlled == null || user != Character.Controlled) { TriggerRewiringSound(); }
ApplyRemoteState(msg);
}
}
private void ApplyRemoteState(IReadMessage msg)
{
List<Wire> prevWires = Connections.SelectMany(c => c.Wires.Where(w => w != null)).ToList();
List<Wire> newWires = new List<Wire>();
ushort userID = msg.ReadUInt16();
if (userID == 0)
{
user = null;
}
else
{
user = Entity.FindEntityByID(userID) as Character;
base.IsActive = true;
}
foreach (Connection connection in Connections)
{
connection.ClearConnections();
}
foreach (Connection connection in Connections)
{
for (int i = 0; i < Connection.MaxLinked; i++)
{
ushort wireId = msg.ReadUInt16();
if (!(Entity.FindEntityByID(wireId) is Item wireItem)) { continue; }
Wire wireComponent = wireItem.GetComponent<Wire>();
if (wireComponent == null) { continue; }
newWires.Add(wireComponent);
connection.SetWire(i, wireComponent);
wireComponent.Connect(connection, false);
}
}
List<Wire> previousDisconnectedWires = new List<Wire>(DisconnectedWires);
DisconnectedWires.Clear();
ushort disconnectedWireCount = msg.ReadUInt16();
for (int i = 0; i < disconnectedWireCount; i++)
{
ushort wireId = msg.ReadUInt16();
if (!(Entity.FindEntityByID(wireId) is Item wireItem)) { continue; }
Wire wireComponent = wireItem.GetComponent<Wire>();
if (wireComponent == null) { continue; }
DisconnectedWires.Add(wireComponent);
base.IsActive = true;
}
foreach (Wire wire in prevWires)
{
bool connected = wire.Connections[0] != null || wire.Connections[1] != null;
if (!connected)
{
foreach (Item item in Item.ItemList)
{
var connectionPanel = item.GetComponent<ConnectionPanel>();
if (connectionPanel != null && connectionPanel.DisconnectedWires.Contains(wire))
{
connected = true;
break;
}
}
}
if (wire.Item.ParentInventory == null && !connected)
{
wire.Item.Drop(null);
}
}
foreach (Wire disconnectedWire in previousDisconnectedWires)
{
if (disconnectedWire.Connections[0] == null &&
disconnectedWire.Connections[1] == null &&
!DisconnectedWires.Contains(disconnectedWire))
{
disconnectedWire.Item.Drop(dropper: null);
}
}
}
}
}
@@ -0,0 +1,252 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class CustomInterface
{
private readonly List<GUIComponent> uiElements = new List<GUIComponent>();
private GUILayoutGroup uiElementContainer;
private Point ElementMaxSize => new Point(uiElementContainer.Rect.Width, (int)(65 * GUI.yScale));
partial void InitProjSpecific(XElement element)
{
CreateGUI();
GameMain.Instance.OnResolutionChanged += RecreateGUI;
}
private void RecreateGUI()
{
GuiFrame.ClearChildren();
CreateGUI();
UpdateLabelsProjSpecific();
}
private void CreateGUI()
{
uiElements.Clear();
var visibleElements = customInterfaceElementList.Where(ciElement => !string.IsNullOrEmpty(ciElement.Label));
uiElementContainer = new GUILayoutGroup(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center)
{
AbsoluteOffset = GUIStyle.ItemFrameOffset
},
childAnchor: customInterfaceElementList.Count > 1 ? Anchor.TopCenter : Anchor.Center)
{
RelativeSpacing = 0.05f,
Stretch = visibleElements.Count() > 2,
};
float elementSize = Math.Min(1.0f / visibleElements.Count(), 1);
foreach (CustomInterfaceElement ciElement in visibleElements)
{
if (ciElement.ContinuousSignal)
{
var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform)
{
MaxSize = ElementMaxSize
},
TextManager.Get(ciElement.Label, returnNull: true) ?? ciElement.Label)
{
UserData = ciElement
};
tickBox.OnSelected += (tBox) =>
{
if (GameMain.Client == null)
{
TickBoxToggled(tBox.UserData as CustomInterfaceElement, tBox.Selected);
}
else
{
item.CreateClientEvent(this);
}
return true;
};
//reset size restrictions set by the Style to make sure the elements can fit the interface
tickBox.RectTransform.MinSize = new Point(0, 0);
tickBox.RectTransform.MaxSize = new Point(int.MaxValue, int.MaxValue);
uiElements.Add(tickBox);
}
else
{
var btn = new GUIButton(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform),
TextManager.Get(ciElement.Label, returnNull: true) ?? ciElement.Label, style: "DeviceButton")
{
UserData = ciElement
};
btn.OnClicked += (_, userdata) =>
{
if (GameMain.Client == null)
{
ButtonClicked(userdata as CustomInterfaceElement);
}
else
{
GameMain.Client.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.GetComponentIndex(this), userdata as CustomInterfaceElement });
}
return true;
};
//reset size restrictions set by the Style to make sure the elements can fit the interface
btn.RectTransform.MinSize = btn.Frame.RectTransform.MinSize = new Point(0, 0);
btn.RectTransform.MaxSize = btn.Frame.RectTransform.MaxSize = ElementMaxSize;
uiElements.Add(btn);
}
}
}
public override void CreateEditingHUD(SerializableEntityEditor editor)
{
base.CreateEditingHUD(editor);
if (customInterfaceElementList.Count > 0)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(customInterfaceElementList[0]);
PropertyDescriptor labelProperty = properties.Find("Label", false);
PropertyDescriptor signalProperty = properties.Find("Signal", false);
for (int i = 0; i < customInterfaceElementList.Count; i++)
{
editor.CreateStringField(customInterfaceElementList[i],
new SerializableProperty(labelProperty),
customInterfaceElementList[i].Label, "Label #" + (i + 1), "");
editor.CreateStringField(customInterfaceElementList[i],
new SerializableProperty(signalProperty),
customInterfaceElementList[i].Signal, "Signal #" + (i + 1), "");
}
}
}
public void HighlightElement(int index, Color color, float duration, float pulsateAmount = 0.0f)
{
if (index < 0 || index >= uiElements.Count) { return; }
uiElements[index].Flash(color, duration);
if (pulsateAmount > 0.0f)
{
if (uiElements[index] is GUIButton button)
{
button.Frame.Pulsate(Vector2.One, Vector2.One * (1.0f + pulsateAmount), duration);
button.Frame.RectTransform.SetPosition(Anchor.Center);
}
else
{
uiElements[index].Pulsate(Vector2.One, Vector2.One * (1.0f + pulsateAmount), duration);
}
}
}
partial void UpdateProjSpecific()
{
bool elementVisibilityChanged = false;
int visibleElementCount = 0;
foreach (var uiElement in uiElements)
{
if (!(uiElement.UserData is CustomInterfaceElement element)) { continue; }
bool visible = Screen.Selected == GameMain.SubEditorScreen || element.StatusEffects.Any() || (element.Connection != null && element.Connection.Wires.Any(w => w != null));
if (visible) { visibleElementCount++; }
if (uiElement.Visible != visible)
{
uiElement.Visible = visible;
elementVisibilityChanged = true;
}
}
if (elementVisibilityChanged)
{
uiElementContainer.Stretch = visibleElementCount > 2;
uiElementContainer.ChildAnchor = visibleElementCount > 1 ? Anchor.TopCenter : Anchor.Center;
float elementSize = Math.Min(1.0f / visibleElementCount, 1);
foreach (var uiElement in uiElements)
{
uiElement.RectTransform.RelativeSize = new Vector2(1.0f, elementSize);
}
GuiFrame.Visible = visibleElementCount > 0;
}
}
partial void UpdateLabelsProjSpecific()
{
for (int i = 0; i < labels.Length && i < uiElements.Count; i++)
{
if (uiElements[i] is GUIButton button)
{
button.Text = string.IsNullOrWhiteSpace(customInterfaceElementList[i].Label) ?
TextManager.GetWithVariable("connection.signaloutx", "[num]", (i + 1).ToString()) :
customInterfaceElementList[i].Label;
button.TextBlock.Wrap = button.Text.Contains(' ');
}
else if (uiElements[i] is GUITickBox tickBox)
{
tickBox.Text = string.IsNullOrWhiteSpace(customInterfaceElementList[i].Label) ?
TextManager.GetWithVariable("connection.signaloutx", "[num]", (i + 1).ToString()) :
customInterfaceElementList[i].Label;
tickBox.TextBlock.Wrap = tickBox.Text.Contains(' ');
}
}
uiElementContainer.Recalculate();
var textBlocks = new List<GUITextBlock>();
foreach (GUIComponent element in uiElementContainer.Children)
{
if (element is GUIButton btn)
{
if (btn.TextBlock.TextSize.Y > btn.Rect.Height - btn.TextBlock.Padding.Y - btn.TextBlock.Padding.W)
{
btn.RectTransform.RelativeSize = new Vector2(btn.RectTransform.RelativeSize.X, btn.RectTransform.RelativeSize.Y * 1.5f);
}
textBlocks.Add(btn.TextBlock);
}
else if (element is GUITickBox tickBox)
{
textBlocks.Add(tickBox.TextBlock);
}
}
uiElementContainer.Recalculate();
GUITextBlock.AutoScaleAndNormalize(textBlocks);
}
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
{
//extradata contains an array of buttons clicked by the player (or nothing if the player didn't click anything)
for (int i = 0; i < customInterfaceElementList.Count; i++)
{
if (customInterfaceElementList[i].ContinuousSignal)
{
msg.Write(((GUITickBox)uiElements[i]).Selected);
}
else
{
msg.Write(extraData != null && extraData.Any(d => d as CustomInterfaceElement == customInterfaceElementList[i]));
}
}
}
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
for (int i = 0; i < customInterfaceElementList.Count; i++)
{
bool elementState = msg.ReadBoolean();
if (customInterfaceElementList[i].ContinuousSignal)
{
((GUITickBox)uiElements[i]).Selected = elementState;
TickBoxToggled(customInterfaceElementList[i], elementState);
}
else if (elementState)
{
ButtonClicked(customInterfaceElementList[i]);
}
}
}
protected override void RemoveComponentSpecific()
{
GameMain.Instance.OnResolutionChanged -= RecreateGUI;
}
}
}
@@ -0,0 +1,23 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma.Items.Components
{
partial class MotionSensor : IDrawableComponent
{
public Vector2 DrawSize
{
get { return new Vector2(rangeX, rangeY) * 2.0f; }
}
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
{
if (!editing || !MapEntity.SelectedList.Contains(item)) return;
Vector2 pos = item.WorldPosition + detectOffset;
pos.Y = -pos.Y;
GUI.DrawRectangle(spriteBatch, pos - new Vector2(rangeX, rangeY), new Vector2(rangeX, rangeY) * 2.0f, Color.Cyan * 0.5f, isFilled: false, thickness: 2);
}
}
}
@@ -0,0 +1,143 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Terminal : ItemComponent, IClientSerializable, IServerSerializable
{
private GUIListBox historyBox;
private GUITextBlock fillerBlock;
private GUITextBox inputBox;
private bool shouldSelectInputBox;
partial void InitProjSpecific(XElement element)
{
var layoutGroup = new GUILayoutGroup(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset })
{
ChildAnchor = Anchor.TopCenter,
RelativeSpacing = 0.02f,
Stretch = true
};
historyBox = new GUIListBox(new RectTransform(new Vector2(1, .9f), layoutGroup.RectTransform), style: null)
{
AutoHideScrollBar = false
};
// Create fillerBlock to cover historyBox so new values appear at the bottom of historyBox
// This could be removed if GUIListBox supported aligning its children
fillerBlock = new GUITextBlock(new RectTransform(new Vector2(1, 1), historyBox.Content.RectTransform, anchor: Anchor.TopCenter), string.Empty)
{
CanBeFocused = false
};
new GUIFrame(new RectTransform(new Vector2(0.9f, 0.01f), layoutGroup.RectTransform), style: "HorizontalLine");
inputBox = new GUITextBox(new RectTransform(new Vector2(1, .1f), layoutGroup.RectTransform), textColor: Color.LimeGreen)
{
MaxTextLength = MaxMessageLength,
OverflowClip = true,
OnEnterPressed = (GUITextBox textBox, string text) =>
{
if (GameMain.NetworkMember == null)
{
SendOutput(text);
}
else
{
item.CreateClientEvent(this, new object[] { text });
}
textBox.Text = string.Empty;
return true;
}
};
}
public override void OnItemLoaded()
{
base.OnItemLoaded();
if (!string.IsNullOrEmpty(DisplayedWelcomeMessage))
{
ShowOnDisplay(DisplayedWelcomeMessage);
}
}
private void SendOutput(string input)
{
if (input.Length > MaxMessageLength)
{
input = input.Substring(0, MaxMessageLength);
}
OutputValue = input;
item.SendSignal(0, input, "signal_out", null);
ShowOnDisplay(input);
}
partial void ShowOnDisplay(string input)
{
while (historyBox.Content.CountChildren > 60)
{
historyBox.RemoveChild(historyBox.Content.Children.First());
}
GUITextBlock newBlock = new GUITextBlock(
new RectTransform(new Vector2(1, 0), historyBox.Content.RectTransform, anchor: Anchor.TopCenter),
"> " + input,
textColor: Color.LimeGreen, wrap: true)
{
CanBeFocused = false
};
if (fillerBlock != null)
{
float y = fillerBlock.RectTransform.RelativeSize.Y - newBlock.RectTransform.RelativeSize.Y;
if (y > 0)
{
fillerBlock.RectTransform.RelativeSize = new Vector2(1, y);
}
else
{
historyBox.RemoveChild(fillerBlock);
fillerBlock = null;
}
}
historyBox.RecalculateChildren();
historyBox.UpdateScrollBarSize();
historyBox.ScrollBar.BarScrollValue = 1;
}
public override bool Select(Character character)
{
shouldSelectInputBox = true;
return base.Select(character);
}
// This method is overrided instead of the UpdateHUD method because this ensures the input box is selected
// even when the terminal component is selected for the very first time. Doing the input box selection in the
// UpdateHUD method only selects the input box on every terminal selection except for the very first time.
public override void AddToGUIUpdateList()
{
base.AddToGUIUpdateList();
if (shouldSelectInputBox)
{
inputBox.Select();
shouldSelectInputBox = false;
}
}
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
{
msg.Write((string)extraData[2]);
}
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
SendOutput(msg.ReadString());
}
}
}
@@ -0,0 +1,23 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma.Items.Components
{
partial class WifiComponent : IDrawableComponent
{
public Vector2 DrawSize
{
get { return new Vector2(range * 2); }
}
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
{
if (!editing || !MapEntity.SelectedList.Contains(item)) return;
Vector2 pos = new Vector2(item.DrawPosition.X, -item.DrawPosition.Y);
ShapeExtensions.DrawLine(spriteBatch, pos + Vector2.UnitY * range, pos - Vector2.UnitY * range, Color.Cyan * 0.5f, 2);
ShapeExtensions.DrawLine(spriteBatch, pos + Vector2.UnitX * range, pos - Vector2.UnitX * range, Color.Cyan * 0.5f, 2);
ShapeExtensions.DrawCircle(spriteBatch, pos, range, 32, Color.Cyan * 0.5f, 3);
}
}
}
@@ -0,0 +1,446 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Wire : ItemComponent, IDrawableComponent, IServerSerializable, IClientSerializable
{
public static Color higlightColor = Color.LightGreen;
public static Color editorHighlightColor = Color.Yellow;
public static Color editorSelectedColor = Color.Red;
partial class WireSection
{
public void Draw(SpriteBatch spriteBatch, Wire wire, Color color, Vector2 offset, float depth, float width = 0.3f)
{
spriteBatch.Draw(wire.wireSprite.Texture,
new Vector2(start.X + offset.X, -(start.Y + offset.Y)), null, color,
-angle,
new Vector2(0.0f, wire.wireSprite.size.Y / 2.0f),
new Vector2(length / wire.wireSprite.Texture.Width, width),
SpriteEffects.None,
depth);
}
public static void Draw(SpriteBatch spriteBatch, Wire wire, Vector2 start, Vector2 end, Color color, float depth, float width = 0.3f)
{
start.Y = -start.Y;
end.Y = -end.Y;
spriteBatch.Draw(wire.wireSprite.Texture,
start, null, color,
MathUtils.VectorToAngle(end - start),
new Vector2(0.0f, wire.wireSprite.size.Y / 2.0f),
new Vector2((Vector2.Distance(start, end)) / wire.wireSprite.Texture.Width, width),
SpriteEffects.None,
depth);
}
}
private static Sprite defaultWireSprite;
private Sprite overrideSprite;
private Sprite wireSprite;
private static Wire draggingWire;
private static int? selectedNodeIndex;
private static int? highlightedNodeIndex;
public Vector2 DrawSize
{
get { return sectionExtents; }
}
public static Wire DraggingWire
{
get => draggingWire;
}
partial void InitProjSpecific(XElement element)
{
if (defaultWireSprite == null)
{
defaultWireSprite = new Sprite("Content/Items/wireHorizontal.png", new Vector2(0.5f, 0.5f))
{
Depth = 0.85f
};
}
foreach (XElement subElement in element.Elements())
{
if (subElement.Name.ToString().Equals("wiresprite", StringComparison.OrdinalIgnoreCase))
{
overrideSprite = new Sprite(subElement);
break;
}
}
wireSprite = overrideSprite ?? defaultWireSprite;
}
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
{
if (sections.Count == 0 && !IsActive || Hidden)
{
Drawable = false;
return;
}
Vector2 drawOffset = Vector2.Zero;
Submarine sub = item.Submarine;
if (IsActive && sub == null) // currently being rewired, we need to get the sub from the connections in case the wire has been taken outside
{
if (connections[0] != null && connections[0].Item.Submarine != null) { sub = connections[0].Item.Submarine; }
if (connections[1] != null && connections[1].Item.Submarine != null) { sub = connections[1].Item.Submarine; }
}
if (sub != null)
{
drawOffset = sub.DrawPosition + sub.HiddenSubPosition;
}
float depth = item.IsSelected ? 0.0f : wireSprite.Depth + ((item.ID % 100) * 0.00001f);
if (item.IsHighlighted)
{
foreach (WireSection section in sections)
{
section.Draw(spriteBatch, this, Screen.Selected == GameMain.GameScreen ? higlightColor : editorHighlightColor, drawOffset, depth + 0.00001f, 0.7f);
}
}
else if (item.IsSelected)
{
foreach (WireSection section in sections)
{
section.Draw(spriteBatch, this, editorSelectedColor, drawOffset, depth + 0.00001f, 0.7f);
}
}
foreach (WireSection section in sections)
{
section.Draw(spriteBatch, this, item.Color, drawOffset, depth, 0.3f);
}
if (nodes.Count > 0)
{
if (!IsActive)
{
if (connections[0] == null) { DrawHangingWire(spriteBatch, nodes[0] + drawOffset, depth); }
if (connections[1] == null) { DrawHangingWire(spriteBatch, nodes.Last() + drawOffset, depth); }
}
if (IsActive && item.ParentInventory?.Owner is Character user && user == Character.Controlled)// && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance)
{
if (user.CanInteract)
{
Vector2 gridPos = Character.Controlled.Position;
Vector2 roundedGridPos = new Vector2(
MathUtils.RoundTowardsClosest(Character.Controlled.Position.X, Submarine.GridSize.X),
MathUtils.RoundTowardsClosest(Character.Controlled.Position.Y, Submarine.GridSize.Y));
//Vector2 attachPos = GetAttachPosition(user);
if (item.Submarine == null)
{
Structure attachTarget = Structure.GetAttachTarget(item.WorldPosition);
if (attachTarget != null)
{
if (attachTarget.Submarine != null)
{
//set to submarine-relative position
gridPos += attachTarget.Submarine.Position;
roundedGridPos += attachTarget.Submarine.Position;
}
}
}
else
{
gridPos += item.Submarine.Position;
roundedGridPos += item.Submarine.Position;
}
Submarine.DrawGrid(spriteBatch, 14, gridPos, roundedGridPos, alpha: 0.7f);
WireSection.Draw(
spriteBatch, this,
new Vector2(nodes[nodes.Count - 1].X, nodes[nodes.Count - 1].Y) + drawOffset,
new Vector2(newNodePos.X, newNodePos.Y) + drawOffset,
item.Color, 0.0f, 0.3f);
WireSection.Draw(
spriteBatch, this,
new Vector2(newNodePos.X, newNodePos.Y) + drawOffset,
item.DrawPosition,
item.Color, itemDepth, 0.3f);
GUI.DrawRectangle(spriteBatch, new Vector2(newNodePos.X + drawOffset.X, -(newNodePos.Y + drawOffset.Y)) - Vector2.One * 3, Vector2.One * 6, item.Color);
}
else
{
WireSection.Draw(
spriteBatch, this,
new Vector2(nodes[nodes.Count - 1].X, nodes[nodes.Count - 1].Y) + drawOffset,
item.DrawPosition,
item.Color, 0.0f, 0.3f);
}
}
}
if (!editing || !GameMain.SubEditorScreen.WiringMode) { return; }
for (int i = 0; i < nodes.Count; i++)
{
Vector2 drawPos = nodes[i];
if (item.Submarine != null) drawPos += item.Submarine.Position + item.Submarine.HiddenSubPosition;
drawPos.Y = -drawPos.Y;
if ((highlightedNodeIndex == i && item.IsHighlighted) || (selectedNodeIndex == i && item.IsSelected))
{
GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-10, -10), new Vector2(20, 20), editorHighlightColor, false, 0.0f);
}
if (item.IsSelected)
{
GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-5, -5), new Vector2(10, 10), item.Color, true, 0.0f);
}
else
{
GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-3, -3), new Vector2(6, 6), item.Color, true, 0.0f);
}
}
}
private void DrawHangingWire(SpriteBatch spriteBatch, Vector2 start, float depth)
{
float angle = (float)Math.Sin(GameMain.GameScreen.GameTime * 2.0f + item.ID) * 0.2f;
Vector2 endPos = start + new Vector2((float)Math.Sin(angle), -(float)Math.Cos(angle)) * 50.0f;
WireSection.Draw(
spriteBatch, this,
start, endPos,
GUI.Style.Orange, depth + 0.00001f, 0.2f);
WireSection.Draw(
spriteBatch, this,
start, start + (endPos - start) * 0.7f,
item.Color, depth, 0.3f);
}
public static void UpdateEditing(List<Wire> wires)
{
Wire equippedWire =
Character.Controlled?.SelectedItems[0]?.GetComponent<Wire>() ??
Character.Controlled?.SelectedItems[1]?.GetComponent<Wire>();
if (equippedWire != null)
{
if (PlayerInput.PrimaryMouseButtonClicked() && Character.Controlled.SelectedConstruction == null)
{
equippedWire.Use(1.0f, Character.Controlled);
}
return;
}
//dragging a node of some wire
if (draggingWire != null)
{
if (Character.Controlled != null)
{
Character.Controlled.FocusedItem = null;
Character.Controlled.ResetInteract = true;
Character.Controlled.ClearInputs();
}
//cancel dragging
if (!PlayerInput.PrimaryMouseButtonHeld())
{
draggingWire = null;
selectedNodeIndex = null;
}
//update dragging
else
{
MapEntity.DisableSelect = true;
Submarine sub = draggingWire.item.Submarine;
if (draggingWire.connections[0] != null && draggingWire.connections[0].Item.Submarine != null) sub = draggingWire.connections[0].Item.Submarine;
if (draggingWire.connections[1] != null && draggingWire.connections[1].Item.Submarine != null) sub = draggingWire.connections[1].Item.Submarine;
Vector2 nodeWorldPos = GameMain.SubEditorScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
if (sub != null)
{
nodeWorldPos = nodeWorldPos - sub.HiddenSubPosition - sub.Position;
}
if (selectedNodeIndex.HasValue)
{
nodeWorldPos.X = MathUtils.Round(nodeWorldPos.X, Submarine.GridSize.X / 2.0f);
nodeWorldPos.Y = MathUtils.Round(nodeWorldPos.Y, Submarine.GridSize.Y / 2.0f);
draggingWire.nodes[(int)selectedNodeIndex] = nodeWorldPos;
draggingWire.UpdateSections();
}
else
{
if (Vector2.DistanceSquared(nodeWorldPos, draggingWire.nodes[(int)highlightedNodeIndex]) > Submarine.GridSize.X * Submarine.GridSize.X)
{
selectedNodeIndex = highlightedNodeIndex;
}
}
MapEntity.SelectEntity(draggingWire.item);
}
return;
}
//a wire has been selected -> check if we should start dragging one of the nodes
float nodeSelectDist = 10, sectionSelectDist = 5;
highlightedNodeIndex = null;
if (MapEntity.SelectedList.Count == 1 && MapEntity.SelectedList[0] is Item)
{
Wire selectedWire = ((Item)MapEntity.SelectedList[0]).GetComponent<Wire>();
if (selectedWire != null)
{
Vector2 mousePos = GameMain.SubEditorScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
if (selectedWire.item.Submarine != null) mousePos -= (selectedWire.item.Submarine.Position + selectedWire.item.Submarine.HiddenSubPosition);
//left click while holding ctrl -> check if the cursor is on a wire section,
//and add a new node if it is
if (PlayerInput.KeyDown(Keys.RightControl) || PlayerInput.KeyDown(Keys.LeftControl))
{
if (PlayerInput.PrimaryMouseButtonClicked())
{
if (Character.Controlled != null)
{
Character.Controlled.ResetInteract = true;
Character.Controlled.ClearInputs();
}
int closestSectionIndex = selectedWire.GetClosestSectionIndex(mousePos, sectionSelectDist, out _);
if (closestSectionIndex > -1)
{
selectedWire.nodes.Insert(closestSectionIndex + 1, mousePos);
selectedWire.UpdateSections();
}
}
}
else
{
//check if close enough to a node
int closestIndex = selectedWire.GetClosestNodeIndex(mousePos, nodeSelectDist, out _);
if (closestIndex > -1)
{
highlightedNodeIndex = closestIndex;
//start dragging the node
if (PlayerInput.PrimaryMouseButtonHeld())
{
if (Character.Controlled != null)
{
Character.Controlled.ResetInteract = true;
Character.Controlled.ClearInputs();
}
draggingWire = selectedWire;
//selectedNodeIndex = closestIndex;
return;
}
//remove the node
else if (PlayerInput.SecondaryMouseButtonClicked() && closestIndex > 0 && closestIndex < selectedWire.nodes.Count - 1)
{
selectedWire.nodes.RemoveAt(closestIndex);
selectedWire.UpdateSections();
}
}
}
}
}
Wire highlighted = null;
//check which wire is highlighted with the cursor
if (GUI.MouseOn == null)
{
float closestDist = float.PositiveInfinity;
foreach (Wire w in wires)
{
Vector2 mousePos = GameMain.SubEditorScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
if (w.item.Submarine != null) { mousePos -= (w.item.Submarine.Position + w.item.Submarine.HiddenSubPosition); }
int highlightedNode = w.GetClosestNodeIndex(mousePos, highlighted == null ? nodeSelectDist : closestDist, out float dist);
if (highlightedNode > -1)
{
if (dist < closestDist)
{
highlightedNodeIndex = highlightedNode;
highlighted = w;
closestDist = dist;
}
}
if (w.GetClosestSectionIndex(mousePos, highlighted == null ? sectionSelectDist : closestDist, out dist) > -1)
{
//prefer nodes over sections
if (dist + nodeSelectDist * 0.5f < closestDist)
{
highlightedNodeIndex = null;
highlighted = w;
closestDist = dist + nodeSelectDist * 0.5f;
}
}
}
}
if (highlighted != null)
{
highlighted.item.IsHighlighted = true;
if (PlayerInput.PrimaryMouseButtonClicked())
{
MapEntity.DisableSelect = true;
MapEntity.SelectEntity(highlighted.item);
}
}
}
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
int eventIndex = msg.ReadRangedInteger(0, (int)Math.Ceiling(MaxNodeCount / (float)MaxNodesPerNetworkEvent));
int nodeCount = msg.ReadRangedInteger(0, MaxNodesPerNetworkEvent);
int nodeStartIndex = eventIndex * MaxNodesPerNetworkEvent;
Vector2[] nodePositions = new Vector2[nodeStartIndex + nodeCount];
for (int i = 0; i < nodes.Count && i < nodePositions.Length; i++)
{
nodePositions[i] = nodes[i];
}
for (int i = 0; i < nodeCount; i++)
{
nodePositions[nodeStartIndex + i] = new Vector2(msg.ReadSingle(), msg.ReadSingle());
}
if (nodePositions.Any(n => !MathUtils.IsValid(n)))
{
nodes.Clear();
return;
}
nodes = nodePositions.ToList();
UpdateSections();
Drawable = nodes.Any();
}
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
{
int nodeCount = (int)extraData[2];
msg.Write((byte)nodeCount);
if (nodeCount > 0)
{
msg.Write(nodes.Last().X);
msg.Write(nodes.Last().Y);
}
}
}
}