Skip to content

Commit cd4e99b

Browse files
committed
Merge branch 'master' of https://github.com/Simple-Station/Einstein-Engines into den-fixes
2 parents b98d47a + b87cbad commit cd4e99b

File tree

129 files changed

+5048
-876
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+5048
-876
lines changed

Content.Client/Chat/UI/SpeechBubble.cs

+12-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using Content.Client.Chat.Managers;
33
using Content.Shared.CCVar;
44
using Content.Shared.Chat;
5+
using Content.Shared.Speech;
6+
using Robust.Client.GameObjects;
57
using Robust.Client.Graphics;
68
using Robust.Client.UserInterface;
79
using Robust.Client.UserInterface.Controls;
@@ -17,6 +19,8 @@ public abstract class SpeechBubble : Control
1719
[Dependency] private readonly IEntityManager _entityManager = default!;
1820
[Dependency] protected readonly IConfigurationManager ConfigManager = default!;
1921

22+
private readonly SharedTransformSystem _transformSystem;
23+
2024
public enum SpeechType : byte
2125
{
2226
Emote,
@@ -83,6 +87,7 @@ public SpeechBubble(ChatMessage message, EntityUid senderEntity, string speechSt
8387
{
8488
IoCManager.InjectDependencies(this);
8589
_senderEntity = senderEntity;
90+
_transformSystem = _entityManager.System<SharedTransformSystem>();
8691

8792
// Use text clipping so new messages don't overlap old ones being pushed up.
8893
RectClipContent = true;
@@ -139,8 +144,13 @@ protected override void FrameUpdate(FrameEventArgs args)
139144
Modulate = Color.White;
140145
}
141146

142-
var offset = (-_eyeManager.CurrentEye.Rotation).ToWorldVec() * -EntityVerticalOffset;
143-
var worldPos = xform.WorldPosition + offset;
147+
var baseOffset = 0f;
148+
149+
if (_entityManager.TryGetComponent<SpeechComponent>(_senderEntity, out var speech))
150+
baseOffset = speech.SpeechBubbleOffset;
151+
152+
var offset = (-_eyeManager.CurrentEye.Rotation).ToWorldVec() * -(EntityVerticalOffset + baseOffset);
153+
var worldPos = _transformSystem.GetWorldPosition(xform) + offset;
144154

145155
var lowerCenter = _eyeManager.WorldToScreen(worldPos) / UIScale;
146156
var screenPos = lowerCenter - new Vector2(ContentSize.X / 2, ContentSize.Y + _verticalOffsetAchieved);

Content.Client/DeltaV/Hologram/HologramSystem.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public override void Initialize()
1717
{
1818
base.Initialize();
1919

20-
_shader = _protoMan.Index<ShaderPrototype>("Hologram").InstanceUnique();
20+
_shader = _protoMan.Index<ShaderPrototype>("HologramDeltaV").InstanceUnique();
2121
SubscribeLocalEvent<HologramComponent, ComponentShutdown>(OnShutdown);
2222
SubscribeLocalEvent<HologramComponent, ComponentStartup>(OnStartup);
2323
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
using Content.Shared.Holopad;
2+
using Content.Shared.Silicons.StationAi;
3+
using Robust.Client.Graphics;
4+
using Robust.Client.UserInterface;
5+
using Robust.Shared.Player;
6+
using System.Numerics;
7+
8+
namespace Content.Client.Holopad;
9+
10+
public sealed class HolopadBoundUserInterface : BoundUserInterface
11+
{
12+
[Dependency] private readonly ISharedPlayerManager _playerManager = default!;
13+
[Dependency] private readonly IClyde _displayManager = default!;
14+
15+
[ViewVariables]
16+
private HolopadWindow? _window;
17+
18+
public HolopadBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
19+
{
20+
IoCManager.InjectDependencies(this);
21+
}
22+
23+
protected override void Open()
24+
{
25+
base.Open();
26+
27+
_window = this.CreateWindow<HolopadWindow>();
28+
_window.Title = Loc.GetString("holopad-window-title", ("title", EntMan.GetComponent<MetaDataComponent>(Owner).EntityName));
29+
30+
if (this.UiKey is not HolopadUiKey)
31+
{
32+
Close();
33+
return;
34+
}
35+
36+
var uiKey = (HolopadUiKey)this.UiKey;
37+
38+
// AIs will see a different holopad interface to crew when interacting with them in the world
39+
if (uiKey == HolopadUiKey.InteractionWindow && EntMan.HasComponent<StationAiHeldComponent>(_playerManager.LocalEntity))
40+
uiKey = HolopadUiKey.InteractionWindowForAi;
41+
42+
_window.SetState(Owner, uiKey);
43+
_window.UpdateState(new Dictionary<NetEntity, string>());
44+
45+
// Set message actions
46+
_window.SendHolopadStartNewCallMessageAction += SendHolopadStartNewCallMessage;
47+
_window.SendHolopadAnswerCallMessageAction += SendHolopadAnswerCallMessage;
48+
_window.SendHolopadEndCallMessageAction += SendHolopadEndCallMessage;
49+
_window.SendHolopadStartBroadcastMessageAction += SendHolopadStartBroadcastMessage;
50+
_window.SendHolopadActivateProjectorMessageAction += SendHolopadActivateProjectorMessage;
51+
_window.SendHolopadRequestStationAiMessageAction += SendHolopadRequestStationAiMessage;
52+
53+
// If this call is addressed to an AI, open the window in the bottom right hand corner of the screen
54+
if (uiKey == HolopadUiKey.AiRequestWindow)
55+
_window.OpenCenteredAt(new Vector2(1f, 1f));
56+
57+
// Otherwise offset to the left so the holopad can still be seen
58+
else
59+
_window.OpenCenteredAt(new Vector2(0.3333f, 0.50f));
60+
}
61+
62+
protected override void UpdateState(BoundUserInterfaceState state)
63+
{
64+
base.UpdateState(state);
65+
66+
var castState = (HolopadBoundInterfaceState)state;
67+
EntMan.TryGetComponent<TransformComponent>(Owner, out var xform);
68+
69+
_window?.UpdateState(castState.Holopads);
70+
}
71+
72+
public void SendHolopadStartNewCallMessage(NetEntity receiver)
73+
{
74+
SendMessage(new HolopadStartNewCallMessage(receiver));
75+
}
76+
77+
public void SendHolopadAnswerCallMessage()
78+
{
79+
SendMessage(new HolopadAnswerCallMessage());
80+
}
81+
82+
public void SendHolopadEndCallMessage()
83+
{
84+
SendMessage(new HolopadEndCallMessage());
85+
}
86+
87+
public void SendHolopadStartBroadcastMessage()
88+
{
89+
SendMessage(new HolopadStartBroadcastMessage());
90+
}
91+
92+
public void SendHolopadActivateProjectorMessage()
93+
{
94+
SendMessage(new HolopadActivateProjectorMessage());
95+
}
96+
97+
public void SendHolopadRequestStationAiMessage()
98+
{
99+
SendMessage(new HolopadStationAiRequestMessage());
100+
}
101+
}
+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
using Content.Shared.Chat.TypingIndicator;
2+
using Content.Shared.Holopad;
3+
using Robust.Client.GameObjects;
4+
using Robust.Client.Graphics;
5+
using Robust.Client.Player;
6+
using Robust.Shared.Prototypes;
7+
using Robust.Shared.Timing;
8+
using System.Linq;
9+
10+
namespace Content.Client.Holopad;
11+
12+
public sealed class HolopadSystem : SharedHolopadSystem
13+
{
14+
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
15+
[Dependency] private readonly IPlayerManager _playerManager = default!;
16+
[Dependency] private readonly IGameTiming _timing = default!;
17+
18+
public override void Initialize()
19+
{
20+
base.Initialize();
21+
22+
SubscribeLocalEvent<HolopadHologramComponent, ComponentInit>(OnComponentInit);
23+
SubscribeLocalEvent<HolopadHologramComponent, BeforePostShaderRenderEvent>(OnShaderRender);
24+
SubscribeAllEvent<TypingChangedEvent>(OnTypingChanged);
25+
26+
SubscribeNetworkEvent<PlayerSpriteStateRequest>(OnPlayerSpriteStateRequest);
27+
SubscribeNetworkEvent<PlayerSpriteStateMessage>(OnPlayerSpriteStateMessage);
28+
}
29+
30+
private void OnComponentInit(EntityUid uid, HolopadHologramComponent component, ComponentInit ev)
31+
{
32+
if (!TryComp<SpriteComponent>(uid, out var sprite))
33+
return;
34+
35+
UpdateHologramSprite(uid);
36+
}
37+
38+
private void OnShaderRender(EntityUid uid, HolopadHologramComponent component, BeforePostShaderRenderEvent ev)
39+
{
40+
if (ev.Sprite.PostShader == null)
41+
return;
42+
43+
ev.Sprite.PostShader.SetParameter("t", (float)_timing.CurTime.TotalSeconds * component.ScrollRate);
44+
}
45+
46+
private void OnTypingChanged(TypingChangedEvent ev, EntitySessionEventArgs args)
47+
{
48+
var uid = args.SenderSession.AttachedEntity;
49+
50+
if (!Exists(uid))
51+
return;
52+
53+
if (!HasComp<HolopadUserComponent>(uid))
54+
return;
55+
56+
var netEv = new HolopadUserTypingChangedEvent(GetNetEntity(uid.Value), ev.IsTyping);
57+
RaiseNetworkEvent(netEv);
58+
}
59+
60+
private void OnPlayerSpriteStateRequest(PlayerSpriteStateRequest ev)
61+
{
62+
var targetPlayer = GetEntity(ev.TargetPlayer);
63+
var player = _playerManager.LocalSession?.AttachedEntity;
64+
65+
// Ignore the request if received by a player who isn't the target
66+
if (targetPlayer != player)
67+
return;
68+
69+
if (!TryComp<SpriteComponent>(player, out var playerSprite))
70+
return;
71+
72+
var spriteLayerData = new List<PrototypeLayerData>();
73+
74+
if (playerSprite.Visible)
75+
{
76+
// Record the RSI paths, state names and shader paramaters of all visible layers
77+
for (int i = 0; i < playerSprite.AllLayers.Count(); i++)
78+
{
79+
if (!playerSprite.TryGetLayer(i, out var layer))
80+
continue;
81+
82+
if (!layer.Visible ||
83+
string.IsNullOrEmpty(layer.ActualRsi?.Path.ToString()) ||
84+
string.IsNullOrEmpty(layer.State.Name))
85+
continue;
86+
87+
var layerDatum = new PrototypeLayerData();
88+
layerDatum.RsiPath = layer.ActualRsi.Path.ToString();
89+
layerDatum.State = layer.State.Name;
90+
91+
if (layer.CopyToShaderParameters != null)
92+
{
93+
var key = (string)layer.CopyToShaderParameters.LayerKey;
94+
95+
if (playerSprite.LayerMapTryGet(key, out var otherLayerIdx) &&
96+
playerSprite.TryGetLayer(otherLayerIdx, out var otherLayer) &&
97+
otherLayer.Visible)
98+
{
99+
layerDatum.MapKeys = new() { key };
100+
101+
layerDatum.CopyToShaderParameters = new PrototypeCopyToShaderParameters()
102+
{
103+
LayerKey = key,
104+
ParameterTexture = layer.CopyToShaderParameters.ParameterTexture,
105+
ParameterUV = layer.CopyToShaderParameters.ParameterUV
106+
};
107+
}
108+
}
109+
110+
spriteLayerData.Add(layerDatum);
111+
}
112+
}
113+
114+
// Return the recorded data to the server
115+
var evResponse = new PlayerSpriteStateMessage(ev.TargetPlayer, spriteLayerData.ToArray());
116+
RaiseNetworkEvent(evResponse);
117+
}
118+
119+
private void OnPlayerSpriteStateMessage(PlayerSpriteStateMessage ev)
120+
{
121+
UpdateHologramSprite(GetEntity(ev.SpriteEntity), ev.SpriteLayerData);
122+
}
123+
124+
private void UpdateHologramSprite(EntityUid uid, PrototypeLayerData[]? layerData = null)
125+
{
126+
if (!TryComp<SpriteComponent>(uid, out var hologramSprite))
127+
return;
128+
129+
if (!TryComp<HolopadHologramComponent>(uid, out var holopadhologram))
130+
return;
131+
132+
for (int i = hologramSprite.AllLayers.Count() - 1; i >= 0; i--)
133+
hologramSprite.RemoveLayer(i);
134+
135+
if (layerData == null || layerData.Length == 0)
136+
{
137+
layerData = new PrototypeLayerData[1];
138+
layerData[0] = new PrototypeLayerData()
139+
{
140+
RsiPath = holopadhologram.RsiPath,
141+
State = holopadhologram.RsiState
142+
};
143+
}
144+
145+
for (int i = 0; i < layerData.Length; i++)
146+
{
147+
var layer = layerData[i];
148+
layer.Shader = "unshaded";
149+
150+
hologramSprite.AddLayer(layerData[i], i);
151+
}
152+
153+
UpdateHologramShader(uid, hologramSprite, holopadhologram);
154+
}
155+
156+
private void UpdateHologramShader(EntityUid uid, SpriteComponent sprite, HolopadHologramComponent holopadHologram)
157+
{
158+
// Find the texture height of the largest layer
159+
float texHeight = sprite.AllLayers.Max(x => x.PixelSize.Y);
160+
161+
var instance = _prototypeManager.Index<ShaderPrototype>(holopadHologram.ShaderName).InstanceUnique();
162+
instance.SetParameter("color1", new Vector3(holopadHologram.Color1.R, holopadHologram.Color1.G, holopadHologram.Color1.B));
163+
instance.SetParameter("color2", new Vector3(holopadHologram.Color2.R, holopadHologram.Color2.G, holopadHologram.Color2.B));
164+
instance.SetParameter("alpha", holopadHologram.Alpha);
165+
instance.SetParameter("intensity", holopadHologram.Intensity);
166+
instance.SetParameter("texHeight", texHeight);
167+
instance.SetParameter("t", (float)_timing.CurTime.TotalSeconds * holopadHologram.ScrollRate);
168+
169+
sprite.PostShader = instance;
170+
sprite.RaiseShaderEvent = true;
171+
}
172+
}

0 commit comments

Comments
 (0)