Fancy speech bubbles - Names over speech bubbles, and 1:1 chat parity for emotes and LOOC! (#21999)

This commit is contained in:
deathride58
2023-12-04 18:10:49 -05:00
committed by GitHub
parent 0b63ec0299
commit e32ede5882
7 changed files with 154 additions and 100 deletions

View File

@@ -369,7 +369,7 @@ public sealed class ChatUIController : UIController
UpdateChannelPermissions();
}
private void AddSpeechBubble(ChatMessage msg, SpeechBubble.SpeechType speechType, string? prefixText = null, string? prefixEndText = null)
private void AddSpeechBubble(ChatMessage msg, SpeechBubble.SpeechType speechType)
{
var ent = EntityManager.GetEntity(msg.SenderEntity);
@@ -379,22 +379,13 @@ public sealed class ChatUIController : UIController
return;
}
// Kind of shitty way to add prefixes but hey it works!
string Message = prefixText + msg.Message + prefixEndText;
// msg.Message should be the string that a user sent over text, without any added markup.
var messages = SplitMessage(Message);
foreach (var message in messages)
{
EnqueueSpeechBubble(ent, message, speechType);
}
EnqueueSpeechBubble(ent, msg, speechType);
}
private void CreateSpeechBubble(EntityUid entity, SpeechBubbleData speechData)
{
var bubble =
SpeechBubble.CreateSpeechBubble(speechData.Type, speechData.Message, entity, _eye, _manager, EntityManager);
SpeechBubble.CreateSpeechBubble(speechData.Type, speechData.Message, entity);
bubble.OnDied += SpeechBubbleDied;
@@ -428,7 +419,7 @@ public sealed class ChatUIController : UIController
RemoveSpeechBubble(entity, bubble);
}
private void EnqueueSpeechBubble(EntityUid entity, string contents, SpeechBubble.SpeechType speechType)
private void EnqueueSpeechBubble(EntityUid entity, ChatMessage message, SpeechBubble.SpeechType speechType)
{
// Don't enqueue speech bubbles for other maps. TODO: Support multiple viewports/maps?
if (EntityManager.GetComponent<TransformComponent>(entity).MapID != _eye.CurrentMap)
@@ -440,7 +431,7 @@ public sealed class ChatUIController : UIController
_queuedSpeechBubbles.Add(entity, queueData);
}
queueData.MessageQueue.Enqueue(new SpeechBubbleData(contents, speechType));
queueData.MessageQueue.Enqueue(new SpeechBubbleData(message, speechType));
}
public void RemoveSpeechBubble(EntityUid entityUid, SpeechBubble bubble)
@@ -568,7 +559,7 @@ public sealed class ChatUIController : UIController
var msg = queueData.MessageQueue.Dequeue();
queueData.TimeLeft += BubbleDelayBase + msg.Message.Length * BubbleDelayFactor;
queueData.TimeLeft += BubbleDelayBase + msg.Message.Message.Length * BubbleDelayFactor;
// We keep the queue around while it has 0 items. This allows us to keep the timer.
// When the timer hits 0 and there's no messages left, THEN we can clear it up.
@@ -621,52 +612,6 @@ public sealed class ChatUIController : UIController
}
}
private List<string> SplitMessage(string msg)
{
// Split message into words separated by spaces.
var words = msg.Split(' ');
var messages = new List<string>();
var currentBuffer = new List<string>();
// Really shoddy way to approximate word length.
// Yes, I am aware of all the crimes here.
// TODO: Improve this to use actual glyph width etc..
var currentWordLength = 0;
foreach (var word in words)
{
// +1 for the space.
currentWordLength += word.Length + 1;
if (currentWordLength > SingleBubbleCharLimit)
{
// Too long for the current speech bubble, flush it.
messages.Add(string.Join(" ", currentBuffer));
currentBuffer.Clear();
currentWordLength = word.Length;
if (currentWordLength > SingleBubbleCharLimit)
{
// Word is STILL too long.
// Truncate it with an ellipse.
messages.Add($"{word.Substring(0, SingleBubbleCharLimit - 3)}...");
currentWordLength = 0;
continue;
}
}
currentBuffer.Add(word);
}
if (currentBuffer.Count != 0)
{
// Don't forget the last bubble.
messages.Add(string.Join(" ", currentBuffer));
}
return messages;
}
public ChatSelectChannel MapLocalIfGhost(ChatSelectChannel channel)
{
if (channel == ChatSelectChannel.Local && _ghost is {IsGhost: true})
@@ -849,11 +794,7 @@ public sealed class ChatUIController : UIController
case ChatChannel.LOOC:
if (_cfg.GetCVar(CCVars.LoocAboveHeadShow))
{
const string prefixText = "(LOOC: ";
const string prefixEndText = ")";
AddSpeechBubble(msg, SpeechBubble.SpeechType.Looc, prefixText, prefixEndText);
}
AddSpeechBubble(msg, SpeechBubble.SpeechType.Looc);
break;
}
}
@@ -896,7 +837,7 @@ public sealed class ChatUIController : UIController
}
}
private readonly record struct SpeechBubbleData(string Message, SpeechBubble.SpeechType Type);
private readonly record struct SpeechBubbleData(ChatMessage Message, SpeechBubble.SpeechType Type);
private sealed class SpeechBubbleQueueData
{